[英]Role Authorization Not Working with React/ASP.NET Core API
I created a react project with the default react template in asp.net core with individual user accounts.我使用 asp.net 核心中的默认反应模板创建了一个反应项目,其中包含个人用户帐户。 [Authorize] attribute works fine however when I try to implement [Authorize(Roles = "Administrator")] I get a 403 status code. [Authorize] 属性工作正常,但是当我尝试实现 [Authorize(Roles = "Administrator")] 时,我得到一个 403 状态码。
I've added ProfileService to add claims.我添加了 ProfileService 来添加声明。
ProfileService.cs配置文件服务.cs
public class ProfileService : IProfileService
{
protected UserManager<ApplicationUser> mUserManager;
public ProfileService(UserManager<ApplicationUser> userManager)
{
mUserManager = userManager;
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
ApplicationUser user = await mUserManager.GetUserAsync(context.Subject);
IList<string> roles = await mUserManager.GetRolesAsync(user);
IList<Claim> roleClaims = new List<Claim>();
foreach (string role in roles)
{
roleClaims.Add(new Claim(JwtClaimTypes.Role, role));
}
context.IssuedClaims.AddRange(roleClaims);
}
public Task IsActiveAsync(IsActiveContext context)
{
return Task.CompletedTask;
}
}
"role": "Administrator" exists in my JWT token. “角色”:“管理员”存在于我的 JWT 令牌中。
I have the Authorize attribute added to my controller.我在 controller 中添加了 Authorize 属性。
[Authorize(Roles = "Administrator")]
[HttpGet]
public async Task<ActionResult<IEnumerable<Order>>> GetOrders()
{
return await _context.Orders.ToListAsync();
}
I have also configured my Startup.cs as below.我还配置了我的 Startup.cs,如下所示。
Startup.cs启动.cs
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
//services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
// .AddEntityFrameworkStores<ApplicationDbContext>();
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddRoles<IdentityRole>()
.AddRoleManager<RoleManager<IdentityRole>>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
services.AddAuthentication()
.AddIdentityServerJwt();
services.AddAuthorization();
services.Configure<IdentityOptions>(options =>
{
options.ClaimsIdentity.RoleClaimType = JwtClaimTypes.Role;
});
services.AddTransient<IProfileService, ProfileService>();
services.AddControllersWithViews();
services.AddRazorPages();
// In production, the React files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/build";
});
}
Unsure where I'm going wrong with this.不确定我在哪里出错了。
If you want to use the built-in Role authorization, you will have to change the way you assign the role claim from this:如果要使用内置角色授权,则必须更改分配角色声明的方式:
roleClaims.Add(new Claim(JwtClaimTypes.Role, role));
to this:对此:
roleClaims.Add(new Claim(ClaimTypes.Role, role));
the better way will be to use policy-based authorization https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-5.0 .更好的方法是使用基于策略的授权https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-5.0 。
Configure your policy in ConfigureServices :在ConfigureServices中配置您的策略:
services.AddAuthorization(options => { options.AddPolicy("RequireAdministratorRole", policy => policy.RequireClaim(ClaimTypes.Role, "Administrator")); });
In ProfileService在 ProfileService 中
var claims = roles.Select(role => new Claim(ClaimTypes.Role, role)).ToList();
Add to the controller:添加到 controller:
[Authorize(Policy = "RequireAdministratorRole")] [授权(策略=“RequireAdministratorRole”)]
It might not work because of the Microsoft claim name inconsistency can be fixed with:它可能不起作用,因为 Microsoft 声明名称不一致可以通过以下方式修复:
services.Configure<JwtBearerOptions>(options =>
{
var validator = options.SecurityTokenValidators.OfType<JwtSecurityTokenHandler>().SingleOrDefault();
// Turn off Microsoft's JWT handler that maps claim types to .NET's long claim type names
validator.InboundClaimTypeMap = new Dictionary<string, string>();
validator.OutboundClaimTypeMap = new Dictionary<string, string>();
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.