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

如何允许Manager角色访问接口?授权后Swagger调用返回404

问题描述

我想限制AddCategory端点仅允许拥有“Manager”角色的用户访问,但遇到以下问题:

  • 在Swagger中通过Login端点登录成功后,调用AddCategory端点返回404;未登录时调用同样返回404。
  • 移除[Authorize(Roles = "Manager")]特性后,接口可正常工作。
  • 已确认登录用户在UserRoles表中属于Manager角色,仅使用[Authorize]特性时问题依旧。
  • Swagger中Login端点返回200,但无法确认是否真的处于登录状态。

生成JwtToken的代码

var roleId = _appDbContext.UserRoles.Where(x => x.UserId == user.Id)
                .Select(x=>x.RoleId)
                .FirstOrDefault();

var role = _appDbContext.Roles.Where(x=>x.Id==roleId).FirstOrDefault();

var tokenDescriptor = new SecurityTokenDescriptor
{
    Subject = new ClaimsIdentity(new[]
    {
        new Claim("Id", user.Id),
        new Claim(JwtRegisteredClaimNames.Email, user.Email),
        new Claim(JwtRegisteredClaimNames.Sub, user.Email),
        new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
        new Claim(ClaimTypes.Role, role.Name)
    }),
    Expires = DateTime.UtcNow.AddSeconds(30), // 5-10 
    SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};

解码后的JWT内容

{
  "alg": "HS256",
  "typ": "JWT"
}.{
  "Id": "3f4b1e8f-d15c-426e-9aa6-375ac53f27ae",
  "email": "manager@example.com",
  "sub": "manager@example.com",
  "jti": "6e1fb89e-5408-4c61-8258-8d2c7cead4ab",
  "role": "Manager",
  "nbf": 1658758635,
  "exp": 1658758665,
  "iat": 1658758635
}.[Signature]

Program.cs配置代码

var key = Encoding.ASCII.GetBytes("llvudfvkwvepwkdnsnwmuulyvtrawppf");

var tokenValidationParams = new TokenValidationParameters
{
    ValidateIssuerSigningKey = true,
    IssuerSigningKey = new SymmetricSecurityKey(key),
    ValidateIssuer = false,
    ValidateAudience = false,
    ValidateLifetime = true,
    RequireExpirationTime = false,
    ClockSkew = TimeSpan.Zero
};

builder.Services.AddSingleton(tokenValidationParams);

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(jwt =>
{
    jwt.SaveToken = true;
    jwt.TokenValidationParameters = tokenValidationParams;
});


builder.Services.AddIdentity<IdentityUser, IdentityRole>()
            .AddEntityFrameworkStores<AppDbContext>()
            .AddDefaultTokenProviders();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();
解决方案

1. 修复中间件顺序(核心问题)

你的Program.cs中缺少UseAuthentication中间件,且UseAuthorization的调用顺序错误。正确的中间件执行顺序必须是先验证身份,再校验权限:

app.UseHttpsRedirection();

// 先启用身份验证中间件,处理JWT令牌解析
app.UseAuthentication();
// 再启用授权中间件,处理角色/权限校验
app.UseAuthorization();

app.MapControllers();

没有UseAuthentication时,框架无法解析JWT令牌,导致授权流程失败,最终返回404(框架将未通过授权的请求视为资源不存在)。

2. 确保Swagger正确携带Token

在Swagger页面点击右上角的Authorize按钮,输入格式为Bearer {你的JWT令牌}(注意Bearer和令牌之间有空格),然后再调用AddCategory接口,确保请求头包含Authorization字段。

3. AspNetRoleClaims表无需额外数据

你已经在JWT中直接嵌入了role声明,框架会从JWT的role字段读取角色信息,不需要向AspNetRoleClaims表添加任何数据。

4. 验证登录状态的方法

  • 在AddCategory接口中添加调试代码,输出以下值:
    // 检查是否已通过身份验证
    var isAuthenticated = User.Identity.IsAuthenticated;
    // 检查是否属于Manager角色
    var isManager = User.IsInRole("Manager");
    
  • 注意你的Token有效期只有30秒,测试时要及时获取新的Token,避免因Token过期导致授权失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 22:39:20