如何允许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
相关产品推荐
相关产品推荐

