使用多种Identity类型时无法添加Token Providers的问题
解决多Identity类型下的密码重置令牌提供者问题
问题本质
使用AddIdentityCore注册多个独立用户类型时,默认令牌提供者是与用户类型绑定的。直接调用AddDefaultTokenProviders会导致依赖注入容器中同一泛型接口IUserTwoFactorTokenProvider<TUser>的实例冲突,最终只有最后注册的用户类型能获取到正确的令牌提供者。
解决方案
需要为每个用户类型显式命名并注册专属令牌提供者,确保二者的令牌服务相互隔离。
方案1:注册时配置专属令牌提供者(推荐)
修改服务注册代码,为每个用户类型指定唯一的令牌提供者名称,并配置用户选项默认使用该名称的提供者:
// 注册UserTypeA的Identity核心服务 services.AddIdentityCore<UserTypeA>(o => { o.Password.RequireDigit = true; o.Password.RequireLowercase = false; o.Password.RequireUppercase = false; o.Password.RequireNonAlphanumeric = false; o.Password.RequiredLength = 10; o.User.RequireUniqueEmail = false; // 指定UserTypeA默认使用的令牌提供者名称 o.Tokens.DefaultProvider = "UserTypeADefault"; }) .AddRoles<ApplicationRole>() // 为UserTypeA注册带名称的默认令牌提供者 .AddTokenProvider("UserTypeADefault", typeof(DataProtectorTokenProvider<UserTypeA>)); // 注册UserTypeB的Identity核心服务 services.AddIdentityCore<UserTypeB>(o => { o.Password.RequireDigit = true; o.Password.RequireLowercase = false; o.Password.RequireUppercase = false; o.Password.RequireNonAlphanumeric = false; o.Password.RequiredLength = 10; o.User.RequireUniqueEmail = false; // 指定UserTypeB默认使用的令牌提供者名称 o.Tokens.DefaultProvider = "UserTypeBDefault"; }) .AddRoles<ApplicationRole>() // 为UserTypeB注册带名称的默认令牌提供者 .AddTokenProvider("UserTypeBDefault", typeof(DataProtectorTokenProvider<UserTypeB>));
此方案下,密码重置逻辑无需额外修改,系统会自动使用对应用户类型配置的默认令牌提供者。
方案2:生成令牌时显式指定提供者名称
若不想修改服务注册逻辑,可在生成密码重置令牌时,手动传入对应的提供者名称:
// 生成UserTypeA的密码重置令牌 var token = await _userManagerA.GeneratePasswordResetTokenAsync(userA, "UserTypeADefault"); // 生成UserTypeB的密码重置令牌 var token = await _userManagerB.GeneratePasswordResetTokenAsync(userB, "UserTypeBDefault");
注意此方式需配合方案1中的服务注册,确保对应名称的令牌提供者已存在。
失败原因分析
- 直接调用
AddDefaultTokenProviders会给当前用户类型注册名为Default的令牌提供者,但DI容器中同一泛型接口的默认实例会被后注册的覆盖,导致仅最后一个用户类型能正常获取服务。 - 基类继承+
AddIdentity的方式仍基于单一用户类型设计,无法自动实现多用户类型的令牌服务隔离。
内容的提问来源于stack exchange,提问作者T-Rev
相关产品推荐
相关产品推荐

