您不必实现 ProfileService。 ReactJS+ID4 模板已经为前端设置了一个客户端(Client[0]),你只需添加适当的配置,让它将角色放入令牌中。
services
.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddRoles<IdentityRole>() //<- Very important, don't forget
.AddEntityFrameworkStores<AuthDbContext>();
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, AuthDbContext>(x =>
{
x.IdentityResources.Add(new IdentityResource("roles", "Roles", new[] { JwtClaimTypes.Role, ClaimTypes.Role }));
foreach(var c in x.Clients)
{
c.AllowedScopes.Add("roles");
}
foreach (var a in x.ApiResources)
{
a.UserClaims.Add(JwtClaimTypes.Role);
}
});
在客户端,小心使用角色。根据分配给用户的角色数量,它可以是字符串或字符串数组。我使用 ensureArray 函数来帮助解决这个问题。
isAdmin(user: User|null): boolean {
return this.isInAnyRole(user, ["Admin"]);
}
isInAnyRole(user: User|null, requiredAnyRoles: string[]): boolean {
var authorized = false;
if (user) {
var userRoles = this.ensureArray(user.profile.role);
requiredAnyRoles.forEach(role => {
if (userRoles.indexOf(role) > -1) {
authorized = true;
}
});
}
return authorized;
}
private ensureArray(value: any): string[] {
if (!Array.isArray(value)) {
return [<string>value];
}
return value;
}
然后您可以在服务器端添加策略。
services.AddAuthorization(options =>
{
options.AddPolicy("RequireAdminRole", policy =>
{
policy.RequireClaim(ClaimTypes.Role, "Admin");
});
});
保护你的 api
[Authorize(Policy = "RequireAdminRole")]
[HttpPost()]
public async Task<IActionResult> Post([FromBody] CreateModel model)