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

ASP.NET Core中如何用JWT与角色授权保护路由?

JWT角色授权失效问题解决方案

一、JWT工作机制快速梳理

JWT由**Header(算法/类型)、Payload(用户信息/角色等声明)、Signature(签名验证)**三部分组成:

  1. 服务器生成Token时,将用户角色、用户名等核心信息存入Payload
  2. 客户端通过Cookie存储Token,请求受保护路由时自动携带
  3. 服务器验证Signature合法性后,解析Payload中的角色声明,判断用户是否具备访问权限

二、分步修复方案

1. 确保Token生成时包含角色声明

生成Token必须把用户角色写入Claims集合,否则服务器无法识别用户角色:

// 示例Token生成代码
var claims = new List<Claim>
{
    new Claim(ClaimTypes.Name, user.UserName),
    // 关键:添加角色声明,ClaimTypes.Role是标准角色声明类型
    new Claim(ClaimTypes.Role, user.Role) 
};

var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

var token = new JwtSecurityToken(
    issuer: _configuration["Jwt:Issuer"],
    audience: _configuration["Jwt:Audience"],
    claims: claims,
    expires: DateTime.Now.AddMinutes(30),
    signingCredentials: creds);

// 将Token写入Cookie
Response.Cookies.Append("JwtToken", new JwtSecurityTokenHandler().WriteToken(token), new CookieOptions
{
    HttpOnly = true,
    Secure = _environment.IsProduction(), // 生产环境强制HTTPS
    SameSite = SameSiteMode.Strict,
    Expires = DateTime.Now.AddMinutes(30)
});

2. 修正Program.cs的认证授权配置

必须配置JWT认证从Cookie读取Token,同时开启角色授权支持:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

// 配置JWT认证
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])),
            // 核心:从Cookie中提取Token(默认从Authorization头读取)
            TokenRetriever = request => request.Cookies["JwtToken"]
        };
    });

// 配置授权策略,支持角色验证
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("AdminOnly", policy => policy.RequireRole("Admin"));
});

var app = builder.Build();

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

app.MapControllers();

app.Run();

3. 控制器中正确使用授权属性

两种方式均可,按需选择:

[ApiController]
[Route("api/admin")]
public class AdminController : ControllerBase
{
    // 直接指定允许的角色
    [Authorize(Roles = "Admin")]
    [HttpGet("dashboard")]
    public IActionResult GetAdminDashboard()
    {
        return Ok("仅管理员可访问的仪表盘数据");
    }

    // 使用自定义授权策略(适合复杂场景)
    [Authorize(Policy = "AdminOnly")]
    [HttpPost("settings")]
    public IActionResult UpdateSystemSettings()
    {
        return Ok("系统设置已更新");
    }
}

4. 验证种子数据的角色正确性

确保数据库中种子用户的角色字段与Token生成时的声明匹配:

// 示例种子数据
var adminUser = new ApplicationUser
{
    UserName = "admin@test.com",
    Email = "admin@test.com",
    Role = "Admin" // 必须与Token中的角色声明一致
};
// 将用户添加到数据库

三、常见问题排查

  • Token角色缺失:用本地JWT解析工具检查Payload,确认http://schemas.microsoft.com/ws/2008/06/identity/claims/role字段值为Admin
  • 中间件顺序错误:UseAuthentication()必须在UseAuthorization()之前执行,否则授权逻辑会在认证前触发
  • Cookie配置问题:生产环境需开启Secure=true,确保Cookie仅通过HTTPS传递;SameSite避免跨域Cookie丢失
  • Token验证参数不匹配:生成Token时的Issuer、Audience、Key必须与Program.cs中的配置完全一致,否则会验证失败

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 16:43:10