You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Claims值返回null求助:ASP.NET登录后无法获取自定义Claims

Claims添加成功但检索返回null的问题排查

在Web应用的Account控制器Login动作内,编写了验证用户名密码正确性并向Claims中加载数据的代码。逐行调试时显示数据已成功添加至Claims,但尝试检索这些Claims时却返回null。

相关代码

登录添加Claims的代码

public void SignInUser(string username, string userRole, string userid, bool isPersistent, string UserLevel,
  string User_Company, string EmpName, string DepId) {
  // Initialization.    
  var claims = new List < Claim > ();
  try {
    // Setting    
    claims.Add(new Claim(ClaimTypes.Name, username));
    claims.Add(new Claim(ClaimTypes.Role, userRole));
    claims.Add(new Claim("UserId", userid));
    claims.Add(new Claim("UserLevel", UserLevel));
    claims.Add(new Claim("CompanyID", User_Company));
    claims.Add(new Claim("EmpName", EmpName));
    claims.Add(new Claim("DepId", DepId));

    var claimIdenties = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);
    var ctx = Request.GetOwinContext();
    var authenticationManager = ctx.Authentication;
    // Sign In.    
    authenticationManager.SignIn(new AuthenticationProperties() {
      IsPersistent = isPersistent
    }, claimIdenties);
    var identity = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);

    var claimsPrincipal = new ClaimsPrincipal(identity);
    Thread.CurrentPrincipal = claimsPrincipal;

  } catch (Exception ex) {
    // Info    
    throw ex;
  }
}

检索Claims的代码

var UsrLvl = (User.Identity as ClaimsIdentity).Claims.Where(c => c.Type == "UserLevel").FirstOrDefault();
var UsrID = (User.Identity as ClaimsIdentity).Claims.Where(c => c.Type == "UserId").FirstOrDefault();
var UserDep = (User.Identity as ClaimsIdentity).Claims.Where(c => c.Type == "DepId").FirstOrDefault();

问题现象

  • 数据传入时Claims已正确添加:
    数据传入截图
  • 检索时返回null:
    检索返回null截图

问题原因及解决方法

核心问题1:重复创建身份对象且未利用Owin认证上下文

代码中在调用authenticationManager.SignIn后,又重复创建了ClaimsIdentity和ClaimsPrincipal并设置Thread.CurrentPrincipal,但当前请求的User.Identity并不会立刻更新——User是当前请求上下文的对象,只有下一个请求才会从认证Cookie中读取新的Claims身份。同时在Web环境下,Thread.CurrentPrincipal的作用范围有限,每个请求对应独立线程,不能依赖它来更新当前请求的身份。

核心问题2:同一请求内尝试检索新添加的Claims

如果在调用SignInUser后,立刻在同一个Login动作里执行检索Claims的代码,此时User.Identity还是登录前的旧身份,自然找不到新添加的Claims。

修复步骤

  1. 简化SignInUser代码:移除重复创建身份对象的冗余代码,只保留Owin认证管理器的SignIn逻辑:
public void SignInUser(string username, string userRole, string userid, bool isPersistent, string UserLevel,
  string User_Company, string EmpName, string DepId) {
  var claims = new List<Claim>();
  try {
    claims.Add(new Claim(ClaimTypes.Name, username));
    claims.Add(new Claim(ClaimTypes.Role, userRole));
    claims.Add(new Claim("UserId", userid));
    claims.Add(new Claim("UserLevel", UserLevel));
    claims.Add(new Claim("CompanyID", User_Company));
    claims.Add(new Claim("EmpName", EmpName));
    claims.Add(new Claim("DepId", DepId));

    var claimIdentity = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);
    var ctx = Request.GetOwinContext();
    var authenticationManager = ctx.Authentication;
    authenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, claimIdentity);
  } catch (Exception ex) {
    throw ex;
  }
}
  1. 登录后重定向到其他Action再检索Claims:
    在Login动作完成验证和SignIn后,执行重定向(比如return RedirectToAction("Index", "Home")),然后在目标Action(如Home/Index)中执行检索Claims的代码。

  2. 优化检索代码:使用FindFirst方法简化检索逻辑,同时增加空值判断避免异常:

var usrLvl = (User.Identity as ClaimsIdentity)?.FindFirst("UserLevel");
var usrID = (User.Identity as ClaimsIdentity)?.FindFirst("UserId");
var userDep = (User.Identity as ClaimsIdentity)?.FindFirst("DepId");
  1. 确认Owin中间件配置正确:
    在Startup.cs中确保已启用Cookie认证中间件:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/Account/Login")
});

内容的提问来源于stack exchange,提问作者Dev Beginner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 23:18:33