ASP.NET Identity实现用户与管理员分库存储的Scheme冲突问题
解决ASP.NET Identity双数据库认证Scheme冲突问题
问题根源
连续调用两次AddIdentity<TUser, TRole>会自动注册默认的Identity.Application认证Scheme,导致重复注册抛出异常。要实现普通用户和管理员分库管理,需手动指定各自的认证Scheme,避免默认值冲突。
解决方案步骤
- 改用
AddIdentityCore替代AddIdentity,手动配置身份服务,避免默认Scheme自动注册 - 为普通用户和管理员分别配置独立的认证Scheme及Cookie参数
- 关联
SignInManager、UserManager与对应Scheme和数据库上下文
完整配置示例
Program.cs 核心配置代码
// 配置普通用户身份系统(关联AuthDbContext) builder.Services.AddIdentityCore<ApplicationUser>(options => { options.SignIn.RequireConfirmedAccount = true; }) .AddRoles<UserRole>() .AddEntityFrameworkStores<AuthDbContext>() .AddErrorDescriber<CustomIdentityErrorDescriber>() .AddSignInManager<SignInManager<ApplicationUser>>() .AddDefaultTokenProviders(); // 配置管理员身份系统(关联AdminDbContext) builder.Services.AddIdentityCore<ApplicationAdmin>(options => { options.SignIn.RequireConfirmedAccount = true; }) .AddRoles<AdminRole>() .AddEntityFrameworkStores<AdminDbContext>() .AddErrorDescriber<CustomIdentityErrorDescriber>() .AddSignInManager<SignInManager<ApplicationAdmin>>() .AddDefaultTokenProviders(); // 配置认证服务,添加两个独立的Cookie Scheme builder.Services.AddAuthentication() // 普通用户Cookie Scheme .AddCookie("UserCookieScheme", options => { options.LoginPath = "/Account/Login"; options.AccessDeniedPath = "/Account/AccessDenied"; options.Cookie.Name = "App.UserCookie"; }) // 管理员Cookie Scheme .AddCookie("AdminCookieScheme", options => { options.LoginPath = "/Admin/Account/Login"; options.AccessDeniedPath = "/Admin/Account/AccessDenied"; options.Cookie.Name = "App.AdminCookie"; }); // 配置授权策略 builder.Services.AddAuthorization(options => { // 默认使用普通用户Scheme options.DefaultPolicy = new AuthorizationPolicyBuilder("UserCookieScheme") .RequireAuthenticatedUser() .Build(); // 管理员专属授权策略 options.AddPolicy("AdminOnly", policy => policy.AddAuthenticationSchemes("AdminCookieScheme") .RequireRole("Admin")); });
登录时指定Scheme
普通用户登录Action示例:
public async Task<IActionResult> Login(LoginViewModel model) { // 业务验证逻辑... await _userSignInManager.SignInAsync(user, model.RememberMe, "UserCookieScheme"); return RedirectToAction("Index", "Home"); }
管理员登录Action示例:
public async Task<IActionResult> Login(AdminLoginViewModel model) { // 业务验证逻辑... await _adminSignInManager.SignInAsync(admin, model.RememberMe, "AdminCookieScheme"); return RedirectToAction("Index", "Admin/Home"); }
注意事项
- 确保
AuthDbContext和AdminDbContext分别绑定不同的数据库连接字符串,且迁移已分别应用到对应数据库 - 注入
SignInManager时需通过泛型区分两个实例:private readonly SignInManager<ApplicationUser> _userSignInManager;和private readonly SignInManager<ApplicationAdmin> _adminSignInManager;
内容的提问来源于stack exchange,提问作者cmd-e
相关产品推荐
相关产品推荐

