在 .NET 9/Razor 页面中使用 ASP.NET Identity 和多用户类型模型

问题描述 投票:0回答:1

我正在构建一个 .NET 应用程序,并(目前)将其基于 ASP.NET Identity,因为这似乎是当前“正确”的做事方式。虽然我拥有丰富的编程经验,但这是我第一次不得不从“从头开始”编写登录系统。

话虽这么说,我的应用程序需要 3 种用户类型,但我一生都无法确定如何在身份模型中准确反映这一点,因为这三者的结构截然不同。 为简单起见,我们将它们称为用户、成员和组织管理员。 除了系统管理员之外,组织管理员可能拥有最大的自由度,因为他们下面嵌套有多个成员以及他们代表的多个用户。成员属于一个组织并可以看到其用户,并且每个成员对多个用户负责。 一个用户可以由多个组织代表。

我考虑过将登录用户扩展到用户和成员,然后使用 RBAC 将成员指定为 ORG 管理员,但我无法确定一种不会让 EF 生气的方法来执行此操作。 我完全承认我对 EF 的使用从来都不是很出色,但对 Dapper 等方面的使用则更好。

如果有任何帮助,我将不胜感激。

asp.net-core authentication authorization .net-9.0
1个回答
0
投票

考虑如下用户模型:

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>();

数据库中的数据:

enter image description here

enter image description here

登录后,您可以看到索赔:

enter image description here

现在您可以按照文档以及上面的

OrgRole
声明来设置基于策略的授权以满足您的要求

© www.soinside.com 2019 - 2024. All rights reserved.