我有一个托管在 ASP.NET Core 中的 Blazor WebAssembly (WASM) 应用程序,它使用默认的 ASP.NET Core 身份对用户进行身份验证。
在
Program.cs
的服务器项目中,我有以下代码:
builder.Services.AddIdentity<AppUser, IdentityRole>(options =>
{
options.SignIn.RequireConfirmedAccount = true;
options.User.AllowedUserNameCharacters = "0123456789";
options.User.RequireUniqueEmail = true;
}).AddRoles<IdentityRole>()
.AddRoleManager<RoleManager<IdentityRole>>()
.AddEntityFrameworkStores<DBcontext>().AddDefaultUI();
builder.Services.AddIdentityServer()
.AddApiAuthorization<AppUser, DBcontext>();
在
Program.cs
的客户端项目(wasm)中我写了这个:
builder.Services.AddApiAuthorization();
我添加了一些角色,例如管理员,用户,...通过
UserManager
或 DbContext
注册用户。
注册后
[HttpPost]
public async Task<IdentityResult> AddRole(AppUser user, string RoleName)
{
try
{
var Role = await db.Roles.FirstOrDefaultAsync(r => r.Name == RoleName);
if (Role == null)
{
Role = new IdentityRole()
{
Name = RoleName,
NormalizedName = RoleName.ToUpper()
};
await db.Roles.AddAsync(Role);
await db.SaveChangesAsync();
}
return await um.AddToRoleAsync(user, RoleName);
}
catch (Exception ex)
{
// ....
}
}
并且角色已正确添加到数据库中。
在
AuthorizeView
标签中,我写道:
<AuthorizeView Roles="Admin,User,Owner">
但是用户登录后,该标签的子标签不会显示
经过我的测试,您可以在客户端应用程序中创建自定义用户工厂,并且需要手动启用角色声明。这是一个示例供您参考: 在数据库中,我添加并绑定了一个账户的角色信息:
在我的客户端中,我配置了一个
CustomUserFactory
,它继承了AccountClaimsPrincipalFactory
,用于创建ClaimsPrincipal对象,包含用户的身份信息和声明:
public class CustomUserFactory(IAccessTokenProviderAccessor accessor)
: AccountClaimsPrincipalFactory<RemoteUserAccount>(accessor)
{
public override async ValueTask<ClaimsPrincipal> CreateUserAsync(
RemoteUserAccount account,
RemoteAuthenticationUserOptions options)
{
var user = await base.CreateUserAsync(account, options);
if (user.Identity is not null && user.Identity.IsAuthenticated)
{
var identity = (ClaimsIdentity)user.Identity;
var roleClaims = identity.FindAll(identity.RoleClaimType).ToArray();
if (roleClaims.Any())
{
foreach (var existingClaim in roleClaims)
{
identity.RemoveClaim(existingClaim);
}
var rolesElem =
account.AdditionalProperties[identity.RoleClaimType];
if (options.RoleClaim is not null && rolesElem is JsonElement roles)
{
if (roles.ValueKind == JsonValueKind.Array)
{
foreach (var role in roles.EnumerateArray())
{
var roleValue = role.GetString();
if (!string.IsNullOrEmpty(roleValue))
{
identity.AddClaim(
new Claim(options.RoleClaim, roleValue));
}
}
}
else
{
var roleValue = roles.GetString();
if (!string.IsNullOrEmpty(roleValue))
{
identity.AddClaim(
new Claim(options.RoleClaim, roleValue));
}
}
}
}
}
return user;
}
}
然后在Client应用程序中,在Program文件中注册工厂,并添加角色相关的服务:
builder.Services.AddApiAuthorization(options =>
{
options.UserOptions.RoleClaim = "role";
}).AddAccountClaimsPrincipalFactory<CustomUserFactory>();
在服务器应用程序中: 配置身份服务器:
builder.Services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options =>
{
options.IdentityResources["openid"].UserClaims.Add("role");
options.ApiResources.Single().UserClaims.Add("role");
});
成功登录后,访问
Test
配置授权页面:
@page "/Test"
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
<AuthorizeView Roles="Admin,User,Owner">
<Authorized>
<h3>Welcome, authorized user!</h3>
<p>You have access to this content because you are in one of the following roles: Admin, User, or Owner.</p>
</Authorized>
<NotAuthorized>
<h3>Access Denied</h3>
<p>You do not have permission to view this content.</p>
</NotAuthorized>
</AuthorizeView>
@code {
}
欲了解更多信息,您可以参考此文档