【问题标题】:Remove User from Roles in ASP.NET Identity 2.0.1从 ASP.NET Identity 2.0.1 中的角色中删除用户
【发布时间】:2014-09-11 01:29:04
【问题描述】:

我定制了一些身份系统的功能以满足我的需求。

我有以下 ApplicationUserManager:

public class ApplicationUserManager : UserManager<ApplicationUser, long>
{
    public ApplicationUserManager()
        : base(new UserStore<ApplicationUser, ApplicationRole,
            long, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>(new GestkatDbContext()))
    {
        //PasswordValidator = new MinimumLengthValidator(10);
    }

    public ApplicationUserManager(IUserStore<ApplicationUser,long> store)
        : base(store)
    {

    }

    public static ApplicationUserManager Create(
    IdentityFactoryOptions<ApplicationUserManager> options,
    IOwinContext context)
    {
        var manager = new ApplicationUserManager(
            new UserStore<ApplicationUser, ApplicationRole, long, ApplicationUserLogin,
                ApplicationUserRole,ApplicationUserClaim>(
                context.Get<GestkatDbContext>()));

        // Configure validation logic for usernames
        manager.UserValidator =
            new UserValidator<ApplicationUser,long>(manager)
            {
                AllowOnlyAlphanumericUserNames = false,
                //RequireUniqueEmail = true
            };


        // Configure validation logic for passwords
        manager.PasswordValidator = new PasswordValidator
        {
            RequiredLength = 6,
        };


        // Configure user lockout defaults
        manager.UserLockoutEnabledByDefault = true;
        manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
        manager.MaxFailedAccessAttemptsBeforeLockout = 5;

        return manager;
    }

    public bool CreateUser(ApplicationUser user, string password)
    {
        var idResult = this.Create(user, password);
        return idResult.Succeeded;
    }

    public bool AddUserToRole(long userId, string roleName)
    {
        return this.AddToRole(userId, roleName).Succeeded;
    }

    public bool ClearAllUserRoles(long userId)
    {
        foreach (var role in this.GetRoles(userId))
        {
            if (!this.RemoveFromRole(userId, role).Succeeded)
            {
                return false;
            }
        }
        return true;
    }
}

其他自定义类是:

public class ApplicationUser : IdentityUser<long, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>
{
    public virtual UserInfo UserInfo { get; set; }

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(ApplicationUserManager manager)
    {
        // Note the authenticationType must match the one 
        // defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity =
            await manager.CreateIdentityAsync(this,
                DefaultAuthenticationTypes.ApplicationCookie);

        // Add custom user claims here
        return userIdentity;
    }

}

public class ApplicationRole : IdentityRole<long, ApplicationUserRole>
{
    public ApplicationRole() : base() { }
    public ApplicationRole(string name, string description)
    {
        this.Name = name;
        this.Description = description;
    }
    public virtual string Description { get; set; }
}

public class ApplicationUserRole : IdentityUserRole<long> { }
public class ApplicationUserClaim : IdentityUserClaim<long> { }

public class ApplicationUserLogin : IdentityUserLogin<long> { }

添加用户并将他们添加到角色似乎工作正常。我的问题是当我想从角色中删除用户时。

当我想将用户添加到角色列表时,我开始使用 ClearAllUserRoles(long userId) 方法将用户从他已经存在的所有角色中清除,然后将他添加到每个选定的角色中。像这样:

public ActionResult UserRoles_Update(long RolesSelectedUserId, List<long> SelectedUserRoles)
    {
        if (RolesSelectedUserId == 0)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        userInfoRepository = new GenericRepository<UserInfo>(DB);
        UserInfo uInfo = userInfoRepository.GetByID(RolesSelectedUserId);
        UserManager.ClearAllUserRoles(uInfo.UserLoginInfo.Id);
        foreach (var roleId in SelectedUserRoles)
        {
            var roleName = DB.Roles.FirstOrDefault(m => m.Id == roleId).Name;
            if (!UserManager.AddUserToRole(uInfo.UserLoginInfo.Id, roleName))
            {
                return Json(false);
            }
        }
        return Json(true);
    }

我的问题是ClearAllUserRoles(long userId) 中使用的RemoveFromRole(userId, role) 方法只将我的AspNetUserRoles 表的字段ApplicationUser_IdApplicationRole_Id 置为空,留下字段UserIdRoleId 填充所以当我尝试将用户重新分配给他已经处于以下异常中的角色:

{"Violation of PRIMARY KEY constraint 'PK_dbo.AspNetUserRoles'. Cannot insert duplicate key in object 'dbo.AspNetUserRoles'. The duplicate key value is (16, 1).\r\nThe statement has been terminated."}

我的问题是:

  1. 我的AspNetUserRoles 表是否应该有这 4 列(ApplicationUser_IdApplicationRole_IdUserIdRoleId)或者我在我的数据库上下文的OnModelCreating()method 中做错了什么?

  2. RemoveFromRole(userId, role) 方法是否按预期工作,还是应该删除AspNetUserRoles 表的所有行?

更新

这是我的OnModelCreating()方法:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        if (modelBuilder == null)
        {
            throw new ArgumentNullException("modelBuilder");
        }

        EntityTypeConfiguration<ApplicationUser> table =
            modelBuilder.Entity<ApplicationUser>().ToTable("AspNetUsers");

        table.Property((ApplicationUser u) => u.UserName).IsRequired();

        modelBuilder.Entity<ApplicationUser>().HasMany<ApplicationUserRole>((ApplicationUser u) => u.Roles);
        modelBuilder.Entity<ApplicationUserRole>().HasKey((ApplicationUserRole r) =>
            new { UserId = r.UserId, RoleId = r.RoleId }).ToTable("AspNetUserRoles");

        EntityTypeConfiguration<ApplicationUserLogin> entityTypeConfiguration =
            modelBuilder.Entity<ApplicationUserLogin>().HasKey((ApplicationUserLogin l) =>
                new
                {
                    UserId = l.UserId,
                    LoginProvider = l.LoginProvider,
                    ProviderKey
                        = l.ProviderKey
                }).ToTable("AspNetUserLogins");

        EntityTypeConfiguration<IdentityUserClaim> table1 =
            modelBuilder.Entity<IdentityUserClaim>().ToTable("AspNetUserClaims");

        EntityTypeConfiguration<ApplicationRole> entityTypeConfiguration1 =
            modelBuilder.Entity<ApplicationRole>().ToTable("AspNetRoles");

        entityTypeConfiguration1.Property((ApplicationRole r) => r.Name).IsRequired();

        modelBuilder.Entity<ApplicationUser>()
                .HasRequired(p => p.UserInfo).WithOptional(p => p.UserLoginInfo);
    }

而在我的 Migration 中,创建表是这样的:

CreateTable(
            "dbo.AspNetUserRoles",
            c => new
                {
                    UserId = c.Long(nullable: false),
                    RoleId = c.Long(nullable: false),
                    ApplicationUser_Id = c.Long(),
                    ApplicationRole_Id = c.Long(),
                })
            .PrimaryKey(t => new { t.UserId, t.RoleId })
            .ForeignKey("dbo.AspNetUsers", t => t.ApplicationUser_Id)
            .ForeignKey("dbo.AspNetRoles", t => t.ApplicationRole_Id)
            .Index(t => t.ApplicationUser_Id)
            .Index(t => t.ApplicationRole_Id);

【问题讨论】:

  • ApplicationUserRole 表应该只有UserIdRoleId 列。
  • @DavidG 我认为你是对的,但我不明白为什么要创建额外的列。我已经添加了OnModelCreating()方法,你可以看看吗?
  • 您真的需要OnModelCreating 中的所有代码吗?如果您的上下文继承自IdentityDbContext,这不是几乎为您完成了吗?
  • @DavidG 因为我需要定制身份系统以满足我的需求(为用户添加更多信息,主键为long 而不是string 等)我发现让它工作的方式。你认为这可能是个问题吗?

标签: asp.net asp.net-mvc user-roles asp.net-identity-2


【解决方案1】:

您需要覆盖OnModelBuilding 中外键的默认命名

替换

modelBuilder.Entity<ApplicationUser>().HasMany<ApplicationUserRole>((ApplicationUser u) => u.Roles);

modelBuilder.Entity<ApplicationUser>().HasMany(p => p.Roles).WithRequired().HasForeignKey(p => p.UserId);
modelBuilder.Entity<ApplicationRole>().HasMany(p => p.Users).WithRequired().HasForeignKey(p => p.RoleId);

不过,我建议您在方法开始时调用 base.OnModelCreating(modelBuilder);,并让常用的 IdentityDbContext 为您完成大部分工作。

【讨论】:

    猜你喜欢
    • 2015-03-19
    • 1970-01-01
    • 1970-01-01
    • 2014-08-08
    • 1970-01-01
    • 2013-12-26
    • 2013-10-29
    • 2015-08-30
    • 1970-01-01
    相关资源
    最近更新 更多