.NET Core 3.1 基于角色的 JWT 授权返回 403 禁止
Posted
技术标签:
【中文标题】.NET Core 3.1 基于角色的 JWT 授权返回 403 禁止【英文标题】:.NET Core 3.1 role-based authorization with JWT returns 403 forbidden 【发布时间】:2020-12-01 00:23:16 【问题描述】:我遇到了一个问题,当我尝试在我的控制器中使用 [Authorize(Roles = "Administrator")]
时,它总是返回 403
。我正在使用身份和 JWT 令牌。这是我的Startup.cs
。我在ConfigureServices()
中同时调用app.UseAuthentication()
和app.UseAuthorization()
,但每次返回403
时仍然相同
public void ConfigureServices(IServiceCollection services)
...
services.AddIdentity<User, Role>(options =>
options.Password.RequireDigit = false;
options.Password.RequireLowercase = false;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
options.Password.RequiredUniqueChars = 0;
options.Password.RequiredLength = 6;
options.ClaimsIdentity.UserIdClaimType = "user_id";
options.ClaimsIdentity.UserNameClaimType = "email";
options.ClaimsIdentity.RoleClaimType = "user_role";
)
.AddRoles<Role>()
.AddEntityFrameworkStores<MyDbContext>()
.AddDefaultTokenProviders();
var key = Encoding.UTF8.GetBytes(Configuration["ApplicationSettings:JwtKey"].ToString());
services.AddAuthentication(options =>
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
)
.AddJwtBearer(options =>
options.RequireHttpsMetadata = false;
options.SaveToken = false;
options.TokenValidationParameters = new TokenValidationParameters
ValidateIssuerSigningKey = true,
ValidateAudience = false,
ValidateIssuer = false,
IssuerSigningKey = new SymmetricSecurityKey(key),
ClockSkew = TimeSpan.Zero
;
options.Events = new JwtBearerEvents
OnAuthenticationFailed = context =>
context.HttpContext.Response.StatusCode = StatusCodes.Status401Unauthorized;
return Task.CompletedTask;
;
);
services.AddControllers()
.AddNewtonsoftJson(options =>
options.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
);
...
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
endpoints.MapControllers();
);
这是我创建令牌的方式
private async Task<string> GenerateToken(DataModelUser user)
var key = Encoding.UTF8.GetBytes(_appSettings.JwtKey);
var tokenDescriptor = new SecurityTokenDescriptor
Subject = new ClaimsIdentity(new Claim[]
new Claim("user_role", user.Role.ToString()),
new Claim("user_id", user.Id.ToString()),
new Claim("email", user.Email)
),
Expires = DateTime.UtcNow.AddDays(1),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
;
var tokenHandler = new JwtSecurityTokenHandler();
var securityToken = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(securityToken);
我在我的控制器上添加这样的内容
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class ProfileController : ControllerBase
[HttpGet]
[Authorize(Roles = "Administrator")]
public async Task<IActionResult> Get()
return Ok();
这是我的 JWT 令牌负载!
"user_role": "Administrator",
"user_id": "5a6333f1-9696-4b1c-a8f8-04619ebd686d",
"name": "Admin Admin",
"completed_profile": "False",
"email": "myadminemail@gmail.com",
"nbf": 1597147248,
"exp": 1597233648,
"iat": 1597147248
【问题讨论】:
嗨@Erlan。您是在检查角色“管理员”还是“管理员”?由于在上面的帖子中您提到要检查“管理员”,而在控制器示例中您要检查“管理员”。 @ThomasLuijken 抱歉,写错了,因为我正在检查Administrator
,现在编辑问题!
@Erlan,好的,感谢您的更新。只是为了检查我们没有遗漏任何明显的东西。我希望在这两个地方设置 'user_role' 声明可以解决问题,但显然它没有。您能否将 JWT 令牌中的一部分有效负载也上传到票证中,以便我们可以看到您的令牌的实际内容是什么样的?您可以在jwt.io 处粘贴访问令牌以查看实际有效负载。
@ThomasLuijken 是的,当然,刚刚编辑了问题并从 JWT 令牌添加了有效负载。
【参考方案1】:
我有一个类似的问题,我通过将 RoleClaimType 和 NameClaimType 添加到 TokenValidationParameter 来解决它:
options.TokenValidationParameters = new TokenValidationParameters
ValidateIssuerSigningKey = true,
ValidateAudience = false,
ValidateIssuer = false,
IssuerSigningKey = new SymmetricSecurityKey(key),
ClockSkew = TimeSpan.Zero,
RoleClaimType = IdentityModel.JwtClaimTypes.Role,
NameClaimType = IdentityModel.JwtClaimTypes.Name
;
【讨论】:
谢谢,使用 RoleClaimType 解决了我的问题以上是关于.NET Core 3.1 基于角色的 JWT 授权返回 403 禁止的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET Core WebApi Jwt 基于角色的授权不起作用
ASP.NET Core 3.1 中基于角色的授权,带有 Identity 和 ExternalLogin
NET Core 3.1 MVC 授权/身份验证,带有在单独的 Net Core 3.1 Web Api 中从外部获取的令牌 (JWT)