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

如何在C# Web API的[Authorize]请求中获取JWT Token(Bearer Token)

在MySQL环境下实现JWT令牌的角色验证方案

一、完善JWT令牌生成逻辑,存入角色Claim

你的代码里已经关联了Cargo(角色),只需要在TokenService.GenerateToken方法中把角色信息加入JWT的Claim集合即可:

public static string GenerateToken(Usuario usuario)
{
    var tokenHandler = new JwtSecurityTokenHandler();
    // 从配置文件读取JWT密钥(建议存在appsettings.json中)
    var secretKey = Encoding.ASCII.GetBytes(Configuration["Jwt:SecretKey"]);
    
    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity(new List<Claim>
        {
            new Claim(ClaimTypes.NameIdentifier, usuario.Id.ToString()),
            new Claim(ClaimTypes.Name, $"{usuario.Nome} {usuario.Sobrenome}"),
            // 将角色名称存入Role类型的Claim
            new Claim(ClaimTypes.Role, usuario.Cargo.Nome)
        }),
        // 设置令牌过期时间,比如2小时
        Expires = DateTime.UtcNow.AddHours(2),
        // 使用HMAC-SHA256算法签名令牌
        SigningCredentials = new SigningCredentials(
            new SymmetricSecurityKey(secretKey), 
            SecurityAlgorithms.HmacSha256Signature)
    };

    var token = tokenHandler.CreateToken(tokenDescriptor);
    return tokenHandler.WriteToken(token);
}

二、配置JWT认证中间件

在Program.cs中添加JWT认证和授权服务,确保请求到达接口前先验证令牌有效性:

var builder = WebApplication.CreateBuilder(args);

// 添加JWT认证服务
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            // 验证签名密钥
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(
                Encoding.ASCII.GetBytes(builder.Configuration["Jwt:SecretKey"])),
            // 根据你的业务需求决定是否验证发行方和受众
            ValidateIssuer = false,
            ValidateAudience = false
        };
    });

// 添加授权服务
builder.Services.AddAuthorization();

// 注册MySQL DbContext
builder.Services.AddDbContext<DataBaseContext>(options =>
    options.UseMySql(builder.Configuration.GetConnectionString("DefaultConnection"), 
        ServerVersion.AutoDetect(builder.Configuration.GetConnectionString("DefaultConnection"))));

var app = builder.Build();

// 中间件顺序必须正确:先认证,再授权
app.UseAuthentication();
app.UseAuthorization();

// 映射路由等其他配置
app.MapControllers();

app.Run();

三、修复原认证方法的异步调用问题

原代码中使用.Result调用异步查询容易引发死锁,改成await:

[HttpPost]
[Route("")]
public async Task<IActionResult> Auth([FromBody] AuthRequestModel authRequest)
{
    var checkUsuario = await _dataBaseContext.Usuario
        .Include(u => u.Cargo)
        .FirstOrDefaultAsync(c => c.Email == authRequest.Usuario);

    if (checkUsuario == null) 
         return NotFound("usuario nao encontrado");

    var hash = new Hash(SHA256.Create());
    var senhaCorreta = hash.VerificarSenha(authRequest.Senha, checkUsuario.Senha);

    if (!senhaCorreta)
        return BadRequest("Senha incorreta");

    var userData = new {
        checkUsuario.Nome, 
        checkUsuario.Sobrenome, 
        checkUsuario.Id
    };

    var token = TokenService.GenerateToken(checkUsuario); 
    var response = new {userData, Token = token};

    return Ok(response);
}

四、验证角色的两种方式

1. 使用特性自动验证

在需要限制角色访问的接口上添加[Authorize(Roles = "你的角色名称")],中间件会自动验证令牌中的角色Claim:

[HttpGet("admin-dashboard")]
[Authorize(Roles = "Admin")]
public IActionResult AdminDashboard()
{
    return Ok("只有管理员能访问此页面");
}

2. 手动解码令牌获取角色

如果需要在方法内手动获取或验证角色,可以通过HttpContext.User直接读取Claim:

[HttpGet("user-info")]
[Authorize] // 先验证令牌有效性
public IActionResult GetUserInfo()
{
    // 获取当前用户的ID和角色
    var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
    var userRole = User.FindFirstValue(ClaimTypes.Role);

    // 自定义角色验证逻辑
    if (userRole != "Editor" && userRole != "Admin")
    {
        return Forbid("无操作权限");
    }

    return Ok(new { UserId = userId, Role = userRole });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 14:33:23