ASP.NET Core 6.0如何实现多Identity并配置Program.cs
ASP.NET Core 6.0 多身份继承模型 Program.cs 配置指南
你当前采用的是EF Core TPH(Table Per Hierarchy,层级共用一张表)的身份扩展模型,首先要先修正现有ApplicationDbContext的定义:
核心注意:默认无泛型参数的IdentityDbContext会绑定系统内置的IdentityUser类型,和你自定义的AppUser派生体系不匹配,必须显式指定泛型参数
修正后的DbContext代码如下:
public class ApplicationDbContext : IdentityDbContext<AppUser> // 必须指定自定义用户基类作为泛型参数 { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } // 建议DbSet属性采用大驼峰+复数命名,对齐EF Core约定,减少额外配置 public DbSet<Advertiser> Advertisers { get; set; } public DbSet<Bagger> Baggers { get; set; } } // 用户类定义保持原有逻辑即可 public class AppUser : IdentityUser {} public class Advertiser : AppUser {} public class Bagger : AppUser {}
完成上述修正后,按以下规则组织Program.cs配置即可正常使用两类身份:
- 注册DbContext服务时,正常配置数据库提供程序即可,和普通EF Core注册逻辑一致
- 注册Identity服务时,必须显式指定你自定义的
AppUser作为用户类型,不能使用无泛型参数的默认AddIdentity方法 - 核心注意:认证、授权中间件必须严格按顺序放置:认证中间件在授权中间件之前,二者都要放在路由映射之后、端点路由执行之前,顺序错误会导致认证失效
- 若需要针对不同身份做权限控制,可以单独添加授权策略,校验当前用户对应的实际身份类型
完整的Program.cs参考配置如下:
var builder = WebApplication.CreateBuilder(args); // 1. 注册DbContext builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); // 上方UseSqlServer可替换为你实际使用的数据库提供程序,如UseMySql、UseSqlite等 // 2. 注册Identity服务,指定自定义用户基类 builder.Services.AddDefaultIdentity<AppUser>(options => { // 可按需配置密码规则、登录要求等Identity参数 options.SignIn.RequireConfirmedAccount = false; options.Password.RequireNonAlphanumeric = false; }) .AddEntityFrameworkStores<ApplicationDbContext>(); // 指定修正后的DbContext作为身份存储 // (可选)针对不同身份添加专属授权策略 builder.Services.AddAuthorization(options => { options.AddPolicy("RequireAdvertiser", policy => policy.RequireAssertion(context => context.User.HasClaim(c => c.Type == "IdentityType" && c.Value == nameof(Advertiser)))); options.AddPolicy("RequireBagger", policy => policy.RequireAssertion(context => context.User.HasClaim(c => c.Type == "IdentityType" && c.Value == nameof(Bagger)))); }); // 按需注册MVC/Razor Pages/控制器服务 builder.Services.AddControllersWithViews(); builder.Services.AddRazorPages(); var app = builder.Build(); // 3. 配置中间件管道,注意顺序不要随意调整 if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); // 认证、授权中间件必须放在UseRouting之后,端点映射之前 app.UseAuthentication(); app.UseAuthorization(); // 端点映射 app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.MapRazorPages(); app.Run();
日常使用注意点
- 要查询特定类型的身份用户,直接通过DbContext调用对应DbSet即可,EF Core会自动通过TPH的判别符字段过滤对应类型的数据
- 登录逻辑不需要区分身份类型,用注入的
UserManager<AppUser>和SignInManager<AppUser>完成校验即可,登录后可以通过用户实例的GetType()判断当前用户属于Advertiser还是Bagger - 如果需要在登录时自动写入身份类型的Claim,可以自定义UserClaimsPrincipalFactory实现,不需要在业务代码里重复判断
内容的提问来源于stack exchange,提问作者Ketuf Wtf
相关产品推荐
相关产品推荐

