ASP.NET Core 标识 - UserClaims、UserRoles 和 RoleClaims

Posted

技术标签:

【中文标题】ASP.NET Core 标识 - UserClaims、UserRoles 和 RoleClaims【英文标题】:ASP.NET Core Identity - UserClaims, UserRoles and RoleClaims 【发布时间】:2019-04-18 00:13:58 【问题描述】:

我正在使用 ASP.NET Core Identity 设置应用程序,尽管仔细阅读了该主题,但我仍在努力寻找适合我的要求的应用程序。

熟悉 Reddit 的 subreddit 概念的用户可能会很好地理解我的要求,因为这些概念非常相似。

基本上,我有一个要求,即用户可以是一个“区域”(类似于 subreddit)的版主,而只是另一个“区域”的“用户”。

归结为,当用户登录时,我需要知道他们在各个领域的角色。

我正在为 ASP.NET Core Identity 的 AspNetUserClaims 和 AspNetRoles / AspNetUserRoles 的实际含义而苦苦挣扎。

我正在考虑像这样定义 AspNetRoles:

Id     Name
1000   User
2000   Junior Moderator
3000   Senior Moderator

然后像这样设置 AspNetUserClaims:

Id     UserId     ClaimType      ClaimValue
1      1          area:public1   1000
2      1          area:private1  2000

这意味着 ID 为 1 的用户是“public1”区域的“用户”和“private1”区域的初级版主。

我有很多问题。

首先,通过尝试将两个值填充到“ClaimType”中,这打破了第一范式。

其次,没有参照完整性。

仔细观察 AspNetUserRoles,我发现用户和角色之间存在多对多的关系。除非我将每个可能区域的每个可能角色定义为 AspNetRole,否则我看不出这将如何工作。即便如此,我仍不清楚我将如何以引用安全的方式将其与 AspNetUserClaims 联系起来。

更复杂的是,我不清楚我是只需要声明还是声明和角色的组合。以下问题涉及该主题,但根据我的要求,我没有看到明确的路径:

Best Practices for Roles vs. Claims in ASP.NET Identity

没有理由我不能通过实施像上面这样的解决方案来解决我遇到的问题,并声称“area:public1”,但这与我对系统设计的理解背道而驰。

鉴于上述要求,在 ASP.NET Core Identity 中推荐的实现是什么?

【问题讨论】:

【参考方案1】:

这意味着 ID 为 1 的用户是该区域的“用户” “public1”和“private1”区域的初级版主。

如果要实现Id为1的User有User Role,而User Role有声明public1area类型。

您可以尝试下面的代码来配置数据。

    public class HomeController : Controller

    private readonly UserManager<IdentityUser> _userManager;
    private readonly RoleManager<IdentityRole> _roleManager;
    public HomeController(UserManager<IdentityUser> userManager
        , RoleManager<IdentityRole> roleManager)
    
        _userManager = userManager;
        _roleManager = roleManager;
    
    public async Task<IActionResult> Prepare()
                
        var userRole = await _roleManager.CreateAsync(new IdentityRole("User"));
        var role = await _roleManager.FindByNameAsync("User");
        var roleClaims = await _roleManager.AddClaimAsync(role, new Claim("area", "public1"));
        var user = await _userManager.FindByNameAsync("UserName");

        var roleToUser = await _userManager.AddToRoleAsync(user, "User");
        return Ok("ok");
    

然后,通过

获取用户的声明
    public async Task<IActionResult> Index()
    
        var user = await _userManager.FindByNameAsync("UserName");
        var roles = await _userManager.GetRolesAsync(user);

        var roleClaims = new List<Claim>();
        foreach (var roleName in roles)
        
            var role = await _roleManager.FindByNameAsync(roleName);
            var claims = await _roleManager.GetClaimsAsync(role);
            roleClaims.AddRange(claims);
        

        return View();
    

以上代码需要配置.AddRoles&lt;IdentityRole&gt;()

        services.AddDefaultIdentity<IdentityUser>()
            .AddRoles<IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>();

【讨论】:

让外键指向 AspNetRoleClaims 表是否被认为是一种好习惯?这甚至可能吗?原因是我有一个 Area 表,它用自己的 ID 表示区域,所以在幕后“public1”的 AreaId 可能为 6。所以在这种情况下,我想在 Area 和 RoleClaim 之间建立关系。这有意义吗? @JonHalliday 当然可以,但不建议这样做,否则,您将需要实现自己的RoleManager 以通过id 6 检索public1

以上是关于ASP.NET Core 标识 - UserClaims、UserRoles 和 RoleClaims的主要内容,如果未能解决你的问题,请参考以下文章

“Identity.External”的 ASP.NET Core 标识异常

如何在 ASP.NET Core 2.2 中实现标识

ASP.NET Core 标识 - UserClaims、UserRoles 和 RoleClaims

ASP.NET Core 标识不注入 UserManager<ApplicationUser>

带有标识 2 和 EntityFramework 6(Oracle)的 ASP.NET Core MVC

例外:oauth 状态丢失或无效。 (ASP.NET Core 外部标识符 OAuth)