我正在构建一个 .NET 应用程序,并(目前)将其基于 ASP.NET Identity,因为这似乎是当前“正确”的做事方式。虽然我拥有丰富的编程经验,但这是我第一次不得不从“从头开始”编写登录系统。
话虽这么说,我的应用程序需要 3 种用户类型,但我一生都无法确定如何在身份模型中准确反映这一点,因为这三者的结构截然不同。 为简单起见,我们将它们称为用户、成员和组织管理员。 除了系统管理员之外,组织管理员可能拥有最大的自由度,因为他们下面嵌套有多个成员以及他们代表的多个用户。成员属于一个组织并可以看到其用户,并且每个成员对多个用户负责。 一个用户可以由多个组织代表。
我考虑过将登录用户扩展到用户和成员,然后使用 RBAC 将成员指定为 ORG 管理员,但我无法确定一种不会让 EF 生气的方法来执行此操作。 我完全承认我对 EF 的使用从来都不是很出色,但对 Dapper 等方面的使用则更好。
如果有任何帮助,我将不胜感激。
考虑如下用户模型:
public class AppUser : IdentityUser
{
public virtual List<AppUserOrg>? AppUserOrgs { get; set; }
}
public class Org
{
public int Id { get; set; }
public string? Name { get; set; }
public virtual List<AppUserOrg>? AppUserOrgs { get; set; }
}
public class AppUserOrg
{
public int Id { get;set; }
public string? UserType { get; set; }
public virtual AppUser AppUser { get; set; }
public string UserId { get; set; }
public virtual Org Org { get; set; }
public int OrgId { get;set; }
}
为 EFCore 启用延迟加载:
安装软件包:
Microsoft.EntityFrameworkCore.Proxies
注册身份相关服务:
builder.Services.AddDbContext<IdentityCusUserContext>(
options =>
{
options.UseSqlServer(connectionString);
options.UseLazyLoadingProxies();
});
builder.Services.AddDefaultIdentity<AppUser>(options => options.SignIn.RequireConfirmedAccount = true).AddEntityFrameworkStores<IdentityCusUserContext>();
使用 IUserClaimsPrincipalFactory 将自定义身份添加到 userprinceple
public class CustomClaimsPrincipalFactory :
UserClaimsPrincipalFactory<AppUser>
{
public CustomClaimsPrincipalFactory(
UserManager<AppUser> userManager,
IOptions<IdentityOptions> optionsAccessor)
: base(userManager, optionsAccessor)
{
}
public async override Task<ClaimsPrincipal> CreateAsync(AppUser user)
{
var principal = await base.CreateAsync(user);
var appUserOrgs = user.AppUserOrgs;
foreach(var appUserOrg in appUserOrgs)
{
((ClaimsIdentity)principal.Identity).AddClaims(
new[] { new Claim("OrgRole", String.Format("{0}:{1}", appUserOrg.Org.Name,appUserOrg.UserType)) });
}
return principal;
}
}
在其他身份相关服务之后注册:
builder.Services.AddScoped<IUserClaimsPrincipalFactory<AppUser>,
CustomClaimsPrincipalFactory>();
数据库中的数据:
登录后,您可以看到索赔:
现在您可以按照文档以及上面的
OrgRole
声明来设置基于策略的授权以满足您的要求