ASP.NET Core Identity,如何覆盖 IdentityRole 名称唯一索引?我想存储关于租户的重复名称
ASP.NET Core Identity, How to override IdentityRole Name unique index? I want to store duplicate name with respect to tenant
我正在编写 IdentityRoleManager 的扩展以允许多租户角色。其中角色在不同租户中可以同名,他们可以将自己的声明分配给角色。
如何在 table 中允许重复角色名称?我打算通过 RoleManager 实现的每个租户的角色名称都是唯一的。
尝试过 OnModelCreating FluentApi,但它没有像在 EF6 中那样提供要作为注释传递的对象
builder.Entity().ToTable("PenRoles")
.属性(p => p.Name).HasAnnotation("Index", new _____{ });
怎么做?
更改角色流畅api配置:
public class RoleConfiguration : IEntityTypeConfiguration<Role>
{
public void Configure(EntityTypeBuilder<Role> builder)
{
builder.Metadata.RemoveIndex(new[] { builder.Property(r => r.NormalizedName).Metadata });
builder.HasIndex(r => new { r.NormalizedName, r.ApplicationId }).HasName("RoleNameIndex").IsUnique();
}
}
然后覆盖 RoleValidator:
public class MyRoleValidator : RoleValidator<Role>
{
public override async Task<IdentityResult> ValidateAsync(RoleManager<Role> manager, Role role)
{
var roleName = await manager.GetRoleNameAsync(role);
if (string.IsNullOrWhiteSpace(roleName))
{
return IdentityResult.Failed(new IdentityError
{
Code = "RoleNameIsNotValid",
Description = "Role Name is not valid!"
});
}
else
{
var owner = await manager.Roles.FirstOrDefaultAsync(x => x.ApplicationId == role.ApplicationId && x.NormalizedName == roleName);
if (owner != null && !string.Equals(manager.GetRoleIdAsync(owner), manager.GetRoleIdAsync(role)))
{
return IdentityResult.Failed(new IdentityError
{
Code = "DuplicateRoleName",
Description = "this role already exist in this App!"
});
}
}
return IdentityResult.Success;
}
}
然后注册到 DI 容器并更改 asp 启动文件中的网络身份配置以使用此 class :
public static IServiceCollection ConfigureIdentity(this IServiceCollection services, IConfiguration configuration)
{
services.AddScoped<IRoleValidator<Role>, MyRoleValidator>(); //this line...
services.AddIdentity<ApplicationUser, Role>(options =>
{
options.Password.RequiredLength = configuration.GetSection(nameof(IdentitySettings)).Get<IdentitySettings>().PasswordRequiredLength;
options.Password.RequireLowercase = configuration.GetSection(nameof(IdentitySettings)).Get<IdentitySettings>().PasswordRequireLowercase;
options.Password.RequireUppercase = configuration.GetSection(nameof(IdentitySettings)).Get<IdentitySettings>().PasswordRequireUppercase;
options.Password.RequireNonAlphanumeric = configuration.GetSection(nameof(IdentitySettings)).Get<IdentitySettings>().PasswordRequireNonAlphanumeric;
options.Password.RequireDigit = configuration.GetSection(nameof(IdentitySettings)).Get<IdentitySettings>().PasswordRequireDigit;
})
.AddRoleValidator<MyRoleValidator>() //this line ...
.AddEntityFrameworkStores<SepidIdentityContext>()
.AddDefaultTokenProviders();
return services;
}
我正在编写 IdentityRoleManager 的扩展以允许多租户角色。其中角色在不同租户中可以同名,他们可以将自己的声明分配给角色。
如何在 table 中允许重复角色名称?我打算通过 RoleManager 实现的每个租户的角色名称都是唯一的。
尝试过 OnModelCreating FluentApi,但它没有像在 EF6 中那样提供要作为注释传递的对象
builder.Entity().ToTable("PenRoles") .属性(p => p.Name).HasAnnotation("Index", new _____{ });
怎么做?
更改角色流畅api配置:
public class RoleConfiguration : IEntityTypeConfiguration<Role>
{
public void Configure(EntityTypeBuilder<Role> builder)
{
builder.Metadata.RemoveIndex(new[] { builder.Property(r => r.NormalizedName).Metadata });
builder.HasIndex(r => new { r.NormalizedName, r.ApplicationId }).HasName("RoleNameIndex").IsUnique();
}
}
然后覆盖 RoleValidator:
public class MyRoleValidator : RoleValidator<Role>
{
public override async Task<IdentityResult> ValidateAsync(RoleManager<Role> manager, Role role)
{
var roleName = await manager.GetRoleNameAsync(role);
if (string.IsNullOrWhiteSpace(roleName))
{
return IdentityResult.Failed(new IdentityError
{
Code = "RoleNameIsNotValid",
Description = "Role Name is not valid!"
});
}
else
{
var owner = await manager.Roles.FirstOrDefaultAsync(x => x.ApplicationId == role.ApplicationId && x.NormalizedName == roleName);
if (owner != null && !string.Equals(manager.GetRoleIdAsync(owner), manager.GetRoleIdAsync(role)))
{
return IdentityResult.Failed(new IdentityError
{
Code = "DuplicateRoleName",
Description = "this role already exist in this App!"
});
}
}
return IdentityResult.Success;
}
}
然后注册到 DI 容器并更改 asp 启动文件中的网络身份配置以使用此 class :
public static IServiceCollection ConfigureIdentity(this IServiceCollection services, IConfiguration configuration)
{
services.AddScoped<IRoleValidator<Role>, MyRoleValidator>(); //this line...
services.AddIdentity<ApplicationUser, Role>(options =>
{
options.Password.RequiredLength = configuration.GetSection(nameof(IdentitySettings)).Get<IdentitySettings>().PasswordRequiredLength;
options.Password.RequireLowercase = configuration.GetSection(nameof(IdentitySettings)).Get<IdentitySettings>().PasswordRequireLowercase;
options.Password.RequireUppercase = configuration.GetSection(nameof(IdentitySettings)).Get<IdentitySettings>().PasswordRequireUppercase;
options.Password.RequireNonAlphanumeric = configuration.GetSection(nameof(IdentitySettings)).Get<IdentitySettings>().PasswordRequireNonAlphanumeric;
options.Password.RequireDigit = configuration.GetSection(nameof(IdentitySettings)).Get<IdentitySettings>().PasswordRequireDigit;
})
.AddRoleValidator<MyRoleValidator>() //this line ...
.AddEntityFrameworkStores<SepidIdentityContext>()
.AddDefaultTokenProviders();
return services;
}