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

在Identity中如何在JWT令牌中携带用户角色及代码问题排查

问题修复方案

一、JWT角色不生效的修复

你当前代码的核心问题是:创建SecurityTokenDescriptor之后才往Claim列表添加角色,但Subject引用的是最初创建的ClaimsIdentity,后续列表的修改不会同步到已生成的ClaimsIdentity中,导致角色无法写入Token。

修改后的Authenticate方法:

public async Task<JwtFeildsDto> Authenticate(string UserName, string PasswordHash)
{
    var user = await _userManager.FindByNameAsync(UserName);
    var roles = await _userManager.GetRolesAsync(user);
    var tokenExpireTimeStamp = DateTime.Now.AddHours(Constansts.JWT_TOKEN_EXPIRE_TIME);
    var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
    var tokenKey = Encoding.ASCII.GetBytes(Constansts.JWT_SECURITY_KEY_FOR_TOKEN);
    
    // 先将所有Claim(含角色)添加到列表,再创建ClaimsIdentity
    var claimList = new List<Claim>()
    {
        new Claim("username", UserName),
        new Claim(ClaimTypes.PrimaryGroupSid,"User Group 01")
    };
    // 提前添加角色到Claim列表
    foreach (var item in roles)
    {
        claimList.Add(new Claim(ClaimTypes.Role, item));  
    }
    
    var securityTokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity(claimList), // 用包含角色的列表创建ClaimsIdentity
        Expires = tokenExpireTimeStamp,
        SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(tokenKey),SecurityAlgorithms.HmacSha256Signature)
    };

    var securityToken = jwtSecurityTokenHandler.CreateToken(securityTokenDescriptor);
    var token = jwtSecurityTokenHandler.WriteToken(securityToken);

    return new JwtFeildsDto
    {
        token = token,
        user_name = UserName,
        expire_time = (int)tokenExpireTimeStamp.Subtract(DateTime.Now).TotalSeconds
    };
}

二、JWTAuthorizationManager实例化问题修复

你的JWTAuthorizationManager构造函数依赖UserManager<User>,但Login方法中直接new JWTAuthorizationManager()未传参,会导致编译错误,同时违反依赖注入原则。

步骤1:注册服务到DI容器

在Program.cs(或Startup.cs)中注册JWTAuthorizationManager:

// .NET 6+ 写法
builder.Services.AddScoped<JWTAuthorizationManager>();

步骤2:通过构造函数注入使用

修改Controller代码,避免手动实例化:

// 你的Controller类
private readonly ILoginService _loginService;
private readonly JWTAuthorizationManager _jwtAuthorizationManager;

// 构造函数注入依赖
public YourController(ILoginService loginService, JWTAuthorizationManager jwtAuthorizationManager)
{
    _loginService = loginService;
    _jwtAuthorizationManager = jwtAuthorizationManager;
}

[HttpPost]
public async Task<IActionResult> Login([FromForm] string userName, string password, bool remmberMe)
{
    if (ModelState.IsValid)
    {
        var result = await _loginService.UserLogin(userName, password, remmberMe);
        if (result == true)
        {
            // 使用注入的实例,注意加await调用异步方法
            var loginResult = await _jwtAuthorizationManager.Authenticate(userName, password);
            return Ok(loginResult);
        }
        else
        {
            return Unauthorized(MessageLib.Message.unaAuthorized);
        }
    }
    return BadRequest();
}

额外验证

生成Token后,可通过JWT解码工具验证Payload中是否包含role字段,确认角色已正确写入。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 19:14:58