使用Microsoft.Owin AD认证时UserPrincipal.EmployeeId登录后无法存储
嘿,我完全懂你现在的困惑——你在SignIn流程里给UserPrincipal.EmployeeId赋值了,但后续在项目其他地方访问这个属性时总是拿到null,核心原因确实和你猜测的一样:你没有把EmployeeId作为Claim添加到ClaimsIdentity中。
为什么会这样?
Owin的Active Directory认证是基于Claims(声明)机制的:你在SignIn时创建的UserPrincipal只是一个临时对象,认证完成后它就会被丢弃,不会被序列化保存到认证票据(比如Cookie)里。只有添加到ClaimsIdentity中的声明,才会被持久化,在后续的请求中可以通过当前用户的身份信息访问到。
怎么解决?
你只需要修改CreateIdentity方法,把EmployeeId作为一个新的Claim添加进去,然后后续从用户的Claims集合中读取它即可。
第一步:修改CreateIdentity方法,添加EmployeeId的Claim
你可以选择使用.NET内置的Claim类型(比如ClaimTypes.SerialNumber),或者自定义一个更直观的Claim类型,比如"EmployeeId"。这里两种方式都给你示例:
private ClaimsIdentity CreateIdentity(UserPrincipal userPrincipal) { var identity = new ClaimsIdentity(ActiveDirectoryAuthentication.ApplicationCookie, ClaimsIdentity.DefaultNameClaimType, ClaimsIdentity.DefaultRoleClaimType); identity.AddClaim(new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "Active Directory")); identity.AddClaim(new Claim(ClaimTypes.Name, userPrincipal.SamAccountName)); identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, userPrincipal.SamAccountName)); // 添加EmployeeId的Claim,这里用自定义类型更清晰 if (!string.IsNullOrEmpty(userPrincipal.EmployeeId)) { identity.AddClaim(new Claim("EmployeeId", userPrincipal.EmployeeId)); // 或者用内置类型: // identity.AddClaim(new Claim(ClaimTypes.SerialNumber, userPrincipal.EmployeeId)); } return identity; }
第二步:在项目其他地方读取EmployeeId
后续你需要从当前用户的Claims集合中获取这个值,而不是再去访问UserPrincipal.EmployeeId(因为那个临时对象已经不存在了)。比如在Controller里:
// 获取当前用户的EmployeeId var employeeId = User.Claims.FirstOrDefault(c => c.Type == "EmployeeId")?.Value; // 如果用了内置的SerialNumber类型,就改成: // var employeeId = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.SerialNumber)?.Value;
小提示
为了避免拼写错误,你可以把自定义的Claim类型定义成常量:
public static class CustomClaimTypes { public const string EmployeeId = "EmployeeId"; }
这样添加和读取的时候都用CustomClaimTypes.EmployeeId,就不会出现因字符串拼写错误导致拿不到值的问题了。
内容的提问来源于stack exchange,提问作者Matt D
相关产品推荐
相关产品推荐

