C# .Net Core 2 JWT、Angular 2角色授权不起作用
我在JWT生成的令牌中有以下有用的负载 { “分包商”:flamelsoft@gmail.com", “jti”:“0bca1034-f3ce-4f72-bd91-65c1a61924c4”, “”:“管理员”, “经验”:1509480891, “iss”:“, “澳元”:” } 使用此代码 Startup.csC# .Net Core 2 JWT、Angular 2角色授权不起作用,c#,asp.net-core-mvc,jwt,asp.net-core-2.0,angular2-jwt,C#,Asp.net Core Mvc,Jwt,Asp.net Core 2.0,Angular2 Jwt,我在JWT生成的令牌中有以下有用的负载 { “分包商”:flamelsoft@gmail.com", “jti”:“0bca1034-f3ce-4f72-bd91-65c1a61924c4”, “”:“管理员”, “经验”:1509480891, “iss”:“, “澳元”:” } 使用此代码 Startup.cs public void ConfigureServices(IServiceCollection services) { services.A
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<DBContextSCM>(options =>
options.UseMySql(Configuration.GetConnectionString("DefaultConnection"), b =>
b.MigrationsAssembly("FlamelsoftSCM")));
services.AddIdentity<User, Role>()
.AddEntityFrameworkStores<DBContextSCM>()
.AddDefaultTokenProviders();
services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
services.AddAuthentication()
.AddJwtBearer(cfg =>
{
cfg.RequireHttpsMetadata = false;
cfg.SaveToken = true;
cfg.TokenValidationParameters = new TokenValidationParameters()
{
ValidIssuer = Configuration["Tokens:Issuer"],
ValidAudience = Configuration["Tokens:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Tokens:Key"]))
};
});
services.AddMvc();
}
问题是角色的验证不起作用,请求到达控制器并在头中返回代码200,但从未进入类。
当我删除[Authorize(Roles=“Administrator”)]时,它会正确输入我的代码。
有什么定义不清的吗?或者,通过角色定义授权的替代方法是什么。TL;博士
如原问题评论中所述,更改为:
[HttpPost]
[授权(角色=“管理员”)]
公共异步任务寄存器([FromBody]寄存器模型)
{
//代码
}
到
[HttpPost]
[授权(AuthenticationSchemes=“承载人”,Roles=“管理员”)]
公共异步任务寄存器([FromBody]寄存器模型)
{
//代码
}
解决了这个问题
承载
是在ASP.NET核心中使用JWT承载身份验证时的首选
但是为什么我们需要在
[Authorize]
属性上指定AuthenticationSchemes
属性呢
这是因为配置身份验证方案并不意味着它们将在每个HTTP请求上运行。如果匿名用户可以访问特定的操作,为什么还要从cookie或令牌中提取用户信息呢?MVC在这方面很聪明,只会在需要时运行身份验证处理程序,也就是说,在某种程度上受到保护的请求期间运行身份验证处理程序
在我们的例子中,MVC发现了[Authorize]
属性,因此知道它必须运行身份验证和授权来确定请求是否被授权。诀窍在于它将只运行已指定的。在这里,我们没有身份验证,因此没有执行身份验证,这意味着授权失败,因为请求被认为是匿名的
向属性添加身份验证方案指示MVC运行该处理程序,该处理程序从HTTP请求中的令牌中提取用户信息,从而发现管理员
角色,请求被允许
作为补充说明,还有另一种方法可以实现这一点,而无需使用
[Authorize]
属性的AuthenticationSchemes
属性
假设您的应用程序只配置了一个身份验证方案,那么在每个[Authorize]
属性上指定authorizationschemes
属性将是一件痛苦的事情
使用ASP.NET Core,您可以配置默认身份验证方案。这样做意味着将为每个HTTP请求运行关联的处理程序,而不管资源是否受到保护
此设置分两部分进行:
公共类启动
{
public void配置服务(IServiceCollection服务)
{
服务
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme/*设置默认的身份验证方案*/)
.AddJwtBearer(选项=>
{
//在此处配置选项
});
}
公共void配置(IApplicationBuilder应用程序)
{
//这将插入将执行
//每个请求上的默认身份验证方案处理程序
app.UseAuthentication();
app.UseMvc();
}
}
这样做意味着,当MVC评估请求是否被授权时,身份验证已经发生,因此不为[Authorize]
属性的AuthenticationSchemes
属性指定任何值将不会成为问题
流程的授权部分仍将运行,并根据已验证的用户检查他们是否属于
管理员组。我知道这个问题已经有了答案,但这里遗漏了一些重要的内容。您需要确保您正在为登录用户实际设置声明。在我的例子中,我使用的是JWT身份验证,因此这一步非常重要:
var claims = new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, user.UserName) });
var roles = await _userManager.GetRolesAsync(user);
if (roles.Count > 0)
{
foreach (var role in roles) { claims.AddClaim(new Claim(ClaimTypes.Role, role)); }
}
var token = new JwtSecurityToken(
issuer: _configuration["JWT:Issuer"],
audience: _configuration["JWT:Audience"],
expires: DateTime.UtcNow.AddMinutes(15),
signingCredentials: signingCredentials,
claims: claims.Claims);
我绞尽脑汁想弄明白为什么HttpContext.User
没有包括我希望缩小[authorization(Roles=“Admin”)]
问题范围的内容。事实证明,如果您使用的是JWT Auth,则需要记住将声明[]
设置为标识。也许这是通过其他dotnet
方式自动完成的,但是jwt
似乎需要您手动设置
在我为用户设置声明后,[Authorize(Roles=“Whatever”)]
按预期工作。我认为第一步是确定失败的是身份验证还是授权。您能否将[Authorize(Roles=“Administrator”)]
替换为[Authorize]
?这将强制用户成功通过身份验证,但不要求他们是管理员
角色的一部分。根据结果,我们将决定下一步查看的位置。如果我将[Authorize(Roles=“Administrator”)]替换为[Authorize],则正确。我认为问题如下。找不到声明/角色URI。知道如何修复它吗?我建议您使用JWT中间件事件来检查从令牌生成的ClaimsPrincipal
JwtBearerOptions
公开了一个Events
属性,该属性允许您在身份验证过程的不同阶段挂接一些逻辑。身份验证成功后,将调用TokenValidated
方法。检查生成委托人的索赔并给出结果。非常感谢,解决方案如下,[authorize]
export class UserService {
constructor(private http: Http, private config: AppConfig, private currentUser: User) { }
create(user: User) {
return this.http.post(this.config.apiUrl + 'Account/Register', user, this.jwt());
}
private jwt() {
const userJson = localStorage.getItem('currentUser');
this.currentUser = userJson !== null ? JSON.parse(userJson) : new User();
if (this.currentUser && this.currentUser.token) {
let headers = new Headers({ 'Authorization': 'Bearer ' + this.currentUser.token });
return new RequestOptions({ headers: headers });
}
}}
var claims = new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, user.UserName) });
var roles = await _userManager.GetRolesAsync(user);
if (roles.Count > 0)
{
foreach (var role in roles) { claims.AddClaim(new Claim(ClaimTypes.Role, role)); }
}
var token = new JwtSecurityToken(
issuer: _configuration["JWT:Issuer"],
audience: _configuration["JWT:Audience"],
expires: DateTime.UtcNow.AddMinutes(15),
signingCredentials: signingCredentials,
claims: claims.Claims);