如何基于已实现多Identity接口的UserService创建UserManager?
如何基于自定义UserService创建UserManager并在IdentityStartup中配置?
我来一步步给你讲清楚怎么实现,毕竟你已经把UserService的基础架子搭好了,接下来就是把它和UserManager整合到Identity的服务体系里就行。
第一步:确保UserModel满足Identity的基础要求
首先,你的UserModel得包含Identity核心功能所需的属性——毕竟你的UserService实现了那些IUserStore相关接口,这些属性是必须的,比如:
public class UserModel : IUser { public string Id { get; set; } public string UserName { get; set; } public string NormalizedUserName { get; set; } public string Email { get; set; } public string NormalizedEmail { get; set; } public bool EmailConfirmed { get; set; } public string PasswordHash { get; set; } public string SecurityStamp { get; set; } public string ConcurrencyStamp { get; set; } // 这里可以加你自己的业务属性,比如NickName、PhoneNumber等 }
如果嫌手动写这些麻烦,也可以直接继承IdentityUser,它已经帮你封装好了这些基础属性。
第二步:在IdentityStartup中注册服务
接下来就是在你的IdentityStartup类的ConfigureServices方法里,把相关服务注册到DI容器中。这里有两种方式,我推荐用第一种,省心又简洁。
方式一:使用Identity扩展方法(推荐)
这种方式会自动帮你注册UserManager所需的大部分默认服务,同时关联你的UserService作为UserStore:
public void ConfigureServices(IServiceCollection services) { // 先注册你的UserRepository实现,因为UserService依赖它 services.AddScoped<IUserRepository, UserRepository>(); // 替换成你实际的Repository实现类 // 配置Identity核心服务 services.AddIdentityCore<UserModel>(options => { // 这里可以根据你的需求配置Identity选项,比如密码规则 options.Password.RequireDigit = true; options.Password.RequireLowercase = true; options.Password.RequireUppercase = true; options.Password.RequireNonAlphanumeric = false; options.Password.RequiredLength = 6; // 如果需要账号锁定功能,也可以在这里配置 // options.Lockout.MaxFailedAccessAttempts = 5; // options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(15); }) .AddUserStore<UserService>() // 指定我们自定义的UserService作为UserStore .AddUserManager<UserManager<UserModel>>() // 注册UserManager .AddDefaultTokenProviders(); // 添加默认的令牌提供者(比如用于邮箱验证、密码重置) }
因为你的UserService已经实现了IUserStore<UserModel>、IUserLoginStore<UserModel>等多个接口,AddUserStore<UserService>()会自动把这些接口的实现都关联到UserService上,不需要单独注册每个接口。
方式二:手动注册UserManager(适合自定义依赖场景)
如果你需要对UserManager的构造依赖做更精细的控制,可以手动实例化并注册:
public void ConfigureServices(IServiceCollection services) { // 先注册基础依赖 services.AddScoped<IUserRepository, UserRepository>(); services.AddScoped<IUserStore<UserModel>, UserService>(); services.AddScoped<IUserLoginStore<UserModel>, UserService>(); services.AddScoped<IUserPasswordStore<UserModel>, UserService>(); services.AddScoped<IUserSecurityStampStore<UserModel>, UserService>(); services.AddScoped<IUserService, UserService>(); // 注册Identity的基础选项和服务 services.AddOptions<IdentityOptions>(); services.AddScoped<IPasswordHasher<UserModel>, PasswordHasher<UserModel>>(); services.AddScoped<IUserValidator<UserModel>, UserValidator<UserModel>>(); services.AddScoped<IPasswordValidator<UserModel>, PasswordValidator<UserModel>>(); services.AddScoped<ILookupNormalizer, UpperInvariantLookupNormalizer>(); services.AddScoped<IdentityErrorDescriber>(); services.AddScoped<ISecurityStampValidator, SecurityStampValidator<UserModel>>(); services.AddOptions<LockoutOptions>(); // 手动注册UserManager services.AddScoped<UserManager<UserModel>>(sp => { var userStore = sp.GetRequiredService<IUserStore<UserModel>>(); var optionsAccessor = sp.GetRequiredService<IOptions<IdentityOptions>>(); var passwordHasher = sp.GetRequiredService<IPasswordHasher<UserModel>>(); var userValidators = sp.GetServices<IUserValidator<UserModel>>(); var passwordValidators = sp.GetServices<IPasswordValidator<UserModel>>(); var keyNormalizer = sp.GetRequiredService<ILookupNormalizer>(); var errors = sp.GetRequiredService<IdentityErrorDescriber>(); var logger = sp.GetRequiredService<ILogger<UserManager<UserModel>>>(); var securityStampValidator = sp.GetRequiredService<ISecurityStampValidator>(); var userLockoutStore = sp.GetService<IUserLockoutStore<UserModel>>(); var lockoutOptions = sp.GetRequiredService<IOptions<LockoutOptions>>(); return new UserManager<UserModel>( userStore, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, sp, logger, securityStampValidator, userLockoutStore, lockoutOptions); }); }
这种方式灵活性更高,但配置起来也更繁琐,一般推荐用第一种方式就够了。
第三步:使用UserManager
现在你就可以在需要的地方通过依赖注入使用UserManager<UserModel>了,比如在控制器里:
public class AccountController : Controller { private readonly UserManager<UserModel> _userManager; public AccountController(UserManager<UserModel> userManager) { _userManager = userManager; } // 比如实现注册功能 public async Task<IActionResult> Register(RegisterViewModel model) { if (ModelState.IsValid) { var user = new UserModel { UserName = model.UserName, Email = model.Email // 设置其他属性 }; var result = await _userManager.CreateAsync(user, model.Password); if (result.Succeeded) { // 注册成功后的逻辑 return RedirectToAction("Index", "Home"); } foreach (var error in result.Errors) { ModelState.AddModelError(string.Empty, error.Description); } } return View(model); } }
内容的提问来源于stack exchange,提问作者Bryan
相关产品推荐
相关产品推荐

