Skip to main content
 首页 » 编程设计

c#之用户角色/授权在 ASP.NET 身份中不起作用

2024年08月06日28shangdawei

在我们的 DbContext.cs 上有这个(模型构建器)代码

 base.OnModelCreating(modelBuilder); 
 modelBuilder.Entity<IdentityUserLogin>().HasKey<string>(l => l.UserId); 
 modelBuilder.Entity<IdentityRole>().HasKey<string>(r => r.Id); 
 modelBuilder.Entity<IdentityUserRole>().HasKey(r => new { r.RoleId, r.UserId }); 
 modelBuilder.Entity<ApplicationUser>().ToTable("ApplicationUser"); 

授权/用户角色外,一切正常。

检查所有表后,我注意到 IdentityUserRoles 表创建了 4 列:RoleId、UserId、IdentityRole_Id 和 ApplicationUser_Id。

我发现,IdentityRole_Id 和 ApplicationUser_Id [外键] 被映射或使用,而不是 RoleId 和 UserId [主键]。不幸的是,身份 (Id) 数据被插入到 RoleId/UserId 列中,默认情况下 IdenityRole_Id/ApplicationUser_Id 为 NULL

请帮忙。

我的代码:

public class RqDbContext : DbContext 
{ 
    private const string ConnectionString = "RqDbContext"; 
 
    public RqDbContext() : base(ConnectionString) 
    { 
    } 
    public static RqDbContext Create() 
    { 
        return new RqDbContext(); 
    } 
 
 
    // ---------------------------------------------------------------------- 
    // Data Tables 
    // ---------------------------------------------------------------------- 
 
    public DbSet<Quote> Quotes { get; set; } 
 
    public DbSet<Booking> Bookings { get; set; } 
 
    public DbSet<CompanyAccount> CompanyAccounts { get; set; } 
 
    // ---------------------------------------------------------------------- 
    // Security 
    // ---------------------------------------------------------------------- 
 
    public DbSet<ApplicationUserExtend> ApplicationUserExtends { get; set; } 
 
    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    {            
        base.OnModelCreating(modelBuilder); 
        modelBuilder.Entity<IdentityUserLogin>().HasKey<string>(l => l.UserId); 
        modelBuilder.Entity<IdentityRole>().HasKey<string>(r => r.Id); 
        modelBuilder.Entity<IdentityUserRole>().HasKey(r => new { r.RoleId, r.UserId }); 
        modelBuilder.Entity<ApplicationUser>().ToTable("ApplicationUser"); 
 
    } 
 
}  
 
public partial class ApplicationUser : IdentityUser 
{ 
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> 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; 
    } 
    //custom+ 
    public virtual ApplicationUserExtend Extend { get; set; } 
 
} 
 
public class ApplicationUserExtend 
{ 
    public ApplicationUserExtend() 
    { 
 
    } 
 
    [Key] 
    [Display(Name="Id")] 
    [XmlAttribute] 
    public int Id { get; set; } 
 
 
    [Display(Name="Account Id")] 
    [XmlAttribute] 
    public int AccountId { get; set; } 
 
 
    [Display(Name="Active Account Id")] 
    [XmlAttribute] 
    public int ActiveAccountId { get; set; } 
} 
 
 
 
public class RqInitializer : System.Data.Entity.DropCreateDatabaseAlways<RqDbContext> 
{ 
    protected override void Seed(RqDbContext context) 
    { 
 
        var testData = ReadTestData(); 
 
        AddIdentityRoles(context, testData); 
        AddUsers(context, testData); 
 
        MvcUtil.SaveChanges(context); 
    } 
 
    private void AddUsers(RqDbContext context, TestDataDo testData) 
    { 
        var userStore = new UserStore<ApplicationUser>(context); 
        var userManager = new UserManager<ApplicationUser>(userStore); 
        //Roles.Enabled("user","member"); 
        var userIndex = 0; 
 
        foreach (var applicationUser in testData.ApplicationUsers) 
        { 
            var user = new ApplicationUser 
            { 
                UserName = applicationUser.UserName, 
                Email = applicationUser.Email, 
                PhoneNumber = applicationUser.PhoneNumber 
            }; 
 
            if (userIndex > testData.ApplicationUserExtends.Count) 
            { 
                throw new Exception("Make sure you the number of rows in ApplicationUserExtends, matches the number of rows in Users"); 
            } 
 
            user.Extend = new ApplicationUserExtend 
            { 
                AccountId = testData.ApplicationUserExtends[userIndex++].AccountId 
            }; 
 
            userManager.Create(user, applicationUser.Password); 
            //set User Role 
            userManager.AddToRole(user.Id, applicationUser.Role); 
 
            //context.Users.Add(user); 
        } 
        context.SaveChanges(); 
    } 
    private void AddIdentityRoles(RqDbContext context, TestDataDo testData) 
    { 
        var roleStore = new RoleStore<IdentityRole>(context); 
        var roleManager = new RoleManager<IdentityRole>(roleStore); 
 
        foreach (var role in testData.IdentityRoles) 
        { 
            var identity = new IdentityRole(role.Name); 
 
            roleManager.Create(identity); 
        } 
 
        context.SaveChanges(); 
    } 
 
    public static TestDataDo ReadTestData() 
    { 
        var xml = GetResource("Rq.Web.App_Specification.Rq-TestData.xml"); 
        return XmlUtil.SerializeFromString<TestDataDo>(xml); 
    } 
 
    private static string GetResource(string file) 
    { 
        var assembly = Assembly.GetExecutingAssembly(); 
        return ResourceUtil.GetAsString(assembly, file); 
    } 
} 
 
// Configure the application user manager used in this application. UserManager is defined in ASP.NET Identity and is used by the application. 
public class ApplicationUserManager : UserManager<ApplicationUser> 
{ 
    public ApplicationUserManager(IUserStore<ApplicationUser> store) 
        : base(store) 
    { 
    } 
 
    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)  
    { 
        var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<RqDbContext>())); 
        // Configure validation logic for usernames 
        manager.UserValidator = new UserValidator<ApplicationUser>(manager) 
        { 
            AllowOnlyAlphanumericUserNames = false, 
            RequireUniqueEmail = true 
        }; 
 
        // Configure validation logic for passwords 
        manager.PasswordValidator = new PasswordValidator 
        { 
            RequiredLength = 6, 
            RequireNonLetterOrDigit = true, 
            RequireDigit = true, 
            RequireLowercase = true, 
            RequireUppercase = true, 
        }; 
 
        // Configure user lockout defaults 
        manager.UserLockoutEnabledByDefault = true; 
        manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5); 
        manager.MaxFailedAccessAttemptsBeforeLockout = 5; 
 
        // Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user 
        // You can write your own provider and plug it in here. 
        manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser> 
        { 
            MessageFormat = "Your security code is {0}" 
        }); 
        manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser> 
        { 
            Subject = "Security Code", 
            BodyFormat = "Your security code is {0}" 
        }); 
        manager.EmailService = new EmailService(); 
        manager.SmsService = new SmsService(); 
        var dataProtectionProvider = options.DataProtectionProvider; 
        if (dataProtectionProvider != null) 
        { 
            manager.UserTokenProvider =  
                new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity")); 
        } 
        return manager; 
    } 
} 
 
// Configure the application sign-in manager which is used in this application. 
public class ApplicationSignInManager : SignInManager<ApplicationUser, string> 
{ 
    public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager) 
        : base(userManager, authenticationManager) 
    { 
    } 
 
    public override Task<ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser user) 
    { 
        return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager); 
    } 
 
    public static ApplicationSignInManager Create(IdentityFactoryOptions<ApplicationSignInManager> options, IOwinContext context) 
    { 
        return new ApplicationSignInManager(context.GetUserManager<ApplicationUserManager>(), context.Authentication); 
    } 
} 

请您参考如下方法:

下面的代码将修复 IdentityUserRoles 表的外键问题。

var user = modelBuilder.Entity<TUser>() 
    .ToTable("AspNetUsers"); 
user.HasMany(u => u.Roles).WithRequired().HasForeignKey(ur => ur.UserId); 
user.HasMany(u => u.Claims).WithRequired().HasForeignKey(uc => uc.UserId); 
user.HasMany(u => u.Logins).WithRequired().HasForeignKey(ul => ul.UserId); 
user.Property(u => u.UserName).IsRequired(); 
 
modelBuilder.Entity<TUserRole>() 
    .HasKey(r => new { r.UserId, r.RoleId }) 
    .ToTable("AspNetUserRoles"); 
 
modelBuilder.Entity<TUserLogin>() 
    .HasKey(l => new { l.UserId, l.LoginProvider, l.ProviderKey}) 
    .ToTable("AspNetUserLogins"); 
 
modelBuilder.Entity<TUserClaim>() 
    .ToTable("AspNetUserClaims"); 
 
var role = modelBuilder.Entity<TRole>() 
    .ToTable("AspNetRoles"); 
role.Property(r => r.Name).IsRequired(); 
role.HasMany(r => r.Users).WithRequired().HasForeignKey(ur => ur.RoleId); 

我在这里找到了答案。 Create ASP.NET Identity tables using SQL script !