【问题标题】:User.IsInRole returns false after switching to one role per userUser.IsInRole 在每个用户切换到一个角色后返回 false
【发布时间】:2021-01-19 02:24:00
【问题描述】:

在从默认 AspNetRole 多对多关系切换到每个用户一个角色并创建自定义身份角色后,User.IsInRole("Admin") 始终返回 false。

登录的用户在数据库上下文中播种,而我删除并再次播种用户以匹配每个用户的一个角色。

这是应用用户:

public class ApplicationUser : IdentityUser
{
   // person props

    public string RoleId { get; set; }
    public ApplicationIdentityRole Role { get; set; }
}

还有身份:

 public class ApplicationIdentityRole : IdentityRole<string>
 {
     public List<ApplicationUser> ApplicationUser { get; set; }
 }

这是我的 DBContext:

 public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationIdentityRole, string>
 {
    // DBSets..

    protected override void OnModelCreating(ModelBuilder builder)
    { 
         string ADMIN_ID = _config.GetValue<string>("Tokens:SysUsers:Admin");

         string ADMIN_ROLE_ID = _config.GetValue<string>("Tokens:Roles:Admin");

         builder.Entity<ApplicationIdentityRole>().HasData(new ApplicationIdentityRole
            {
                Id = ADMIN_ROLE_ID,
                Name = "Admin",
                NormalizedName = "ADMIN"
            });

            var hasher = new PasswordHasher<ApplicationUser>();

            builder.Entity<ApplicationUser>().HasData(new ApplicationUser
            {
                Id = ADMIN_ID,
                UserName = "admin",
                NormalizedUserName = "ADMIN",
                Email = "admin@sys.com",
                NormalizedEmail = "ADMIN@SYS.COM",
                EmailConfirmed = true,
                PasswordHash = hasher.HashPassword(null, "123123"),
                SecurityStamp = string.Empty,
                Title = "Admin",
                RoleId = ADMIN_ROLE_ID
            });
    }
}

并且我已更改启动以匹配应用身份角色类:

services.AddIdentity<ApplicationUser, ApplicationIdentityRole>()
                         .AddEntityFrameworkStores<ApplicationDbContext>()
                         .AddDefaultTokenProviders()
                         .AddDefaultUI();

services.AddTransient<UserManager<ApplicationUser>>();

登录:

// sigin manager
private readonly SignInManager<ApplicationUser> _signInManager;

// usage
var result = await _signInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, lockoutOnFailure: false);

授权工作正常,但角色总是返回 false

我意识到从IdentityDbContext&lt;ApplicationUser, ApplicationIdentityRole, string&gt; 继承会生成默认角色表(多对多),所以理论上,它会将添加给用户的角色属性视为一个数据集AspNetRole 并验证多对多表不是RoleId

我找不到任何说明如何使用 ef 为每个用户设置一个角色的文档。

非常感谢任何帮助!

更新:成功登录后,SignInManager 不会将角色添加到声明中,而是仅在AspNetUserRole(多对多)表中有记录时添加我想排除。

【问题讨论】:

    标签: asp.net-core entity-framework-core asp.net-identity


    【解决方案1】:

    授权工作正常,但角色总是返回 假的。

    这是因为登录过程会通过AspNetUserRole 表查找角色数据,而您没有在该表中插入任何数据。

    您可以扩展身份模型,但不能修改它们之间的关系。要查找您必须自定义 Identity 模型的选项,请查看 Identity model customization in ASP.NET Core

    您所做的更改不会影响UserRole 之间的默认多对多关系(查看您的数据库,您仍然会找到连接表AspNetUserRole)。 UserManagerRoleManagerSignInManager 等的内置功能将继续基于该默认关系工作。

    对于您当前的情况:
    对于您的自定义关系,您必须使用自定义方法来访问角色数据。而不是User.IsInRole("Admin"),您必须执行以下操作 -

    var user = context.ApplicationUsers.Include(p=> p.ApplicationIdentityRole).FirstOrDefault(p=> p.UserName == User.Identity.Name);
    var isInRole = user.ApplicationIdentityRole.Name == "Admin";
    

    如果您想要one-role per user,则无需创建额外的关系并增加复杂性。您可以简单地在您的 ApplicationUser 模型中添加一个名为 Role 的属性 -

    public class ApplicationUser : IdentityUser
    {
        public string Role { get; set; }
    }
    

    这样你仍然必须使用自己的方法来访问角色数据(因为你没有使用多对多关系),但现在会更容易 -

    var isInRole = context.ApplicationUsers.FirstOrDefault(p=> p.UserName == User.Identity.Name && p=> p.Role == "Admin");
    

    为了更好的解决方案:
    现在,您正在通过数据播种创建用户和角色。但通常你会想用类似的东西向用户添加新角色 -

    await userManager.AddToRoleAsync(user, "Admin");
    

    这会将角色链接数据放入AspNetUserRole 表中,并且该数据将由登录过程使用,并且您会从User.IsInRole("Admin") 方法获得预期结果。

    因此,如果您真的想限制用户只有一个角色,而一切都按预期工作,您只需要确保不能将多个角色添加到用户。你可以这样做 -

    1. UserManager&lt;ApplicationUser&gt; 类派生,然后覆盖AddToRoleAsync 方法。但就你的目的而言,这将是一个矫枉过正。

    2. 执行以下操作 -

    if ((await userManager.GetRolesAsync(user)).Count == 0)
    {
        await userManager.AddToRoleAsync(user, "Admin");
    }
    

    【讨论】:

      猜你喜欢
      • 2019-08-14
      • 2016-07-29
      • 2015-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-14
      • 2016-01-30
      相关资源
      最近更新 更多