builder.Services.Configure<IdentityOptions>(options => { options.Password.RequiredLength = 8; options.Password.RequireLowercase = true; });下面表格提供了IdentityOptions 类常用的一些属性:
名称 |
描述 |
RequiredLength |
设置密码最少长度 |
RequireNonAlphanumeric |
设置用户名和密码是否有一个非数字和字符.默认值为True. 如果我们不希望有特殊字符,我们可以设置成false.例如: – @, !, #, $. |
RequireLowercase |
当我们设置这个属性为True时, Identity 将要求至少有一个小写字母 |
RequireUppercase |
当我们设置属性为false,Identity 不要求至少有一个大写字母在密码中 |
RequireDigit |
当我们设置属性false,Identity 不要求至少有一个数字在密码中 |
public class CustomPasswordPolicy : PasswordValidator<AppUser> { public override async Task<IdentityResult> ValidateAsync(UserManager<AppUser> manager, AppUser user, string password) { IdentityResult result = await base.ValidateAsync(manager, user, password); List<IdentityError> errors = result.Succeeded ? new List<IdentityError>() : result.Errors.ToList(); if (password.ToLower().Contains(user.UserName.ToLower())) { errors.Add(new IdentityError { Description = "密码不能包含用户名" }); } if (password.Contains("123")) { errors.Add(new IdentityError { Description = "密码不能包含123数字序列" }); } return errors.Count == 0 ? IdentityResult.Success : IdentityResult.Failed(errors.ToArray()); } }PasswordValidator<T>类定义ValidateAsync()方法。我们重写该方法并实现自定义密码策略的逻辑,我们判断密码是否包含用户名和123数组序列,如果包含将相应错误添加到List对象中:
if (password.ToLower().Contains(user.UserName.ToLower())) { errors.Add(new IdentityError { Description = "密码不能包含用户名" }); } if (password.Contains("123")) { errors.Add(new IdentityError { Description = "密码不能包含123数字序列" }); }最后一行
return errors.Count == 0 ? IdentityResult.Success : IdentityResult.Failed(errors.ToArray());我们检查错误个数,如果错误个数为0我们将返回IdentityResult.Success否则返回IdentityResult.Failed返回一个错误列表。IPasswordValidator接口中定义了密码验证功能,我们在启动类中添加该服务
builder.Services.AddTransient<IPasswordValidator<AppUser>, CustomPasswordPolicy>();我们测试一下刚才创建的自定义密码策略功能。运行应用程序,在浏览器中输入如下地址:https://localhost:7296/Admin/Cre
builder.Services.Configure<IdentityOptions>(options => { options.User.RequireUniqueEmail = true; options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyz"; });RequireUniqueEmail属性设置为true,限制用户邮箱必须是唯一
public class CustomUsernameEmailPolicy : UserValidator<AppUser> { //堆代码 duidaima.com public override async Task<IdentityResult> ValidateAsync(UserManager<AppUser> manager, AppUser user) { IdentityResult result = await base.ValidateAsync(manager, user); List<IdentityError> errors =result.Succeeded? new List<IdentityError>() : result.Errors.ToList(); if (user.UserName == "google") { errors.Add(new IdentityError { Description = "Google cannot be used as a user name" }); } if (!user!.Email!.ToLower().EndsWith("@yahoo.com")) { errors.Add(new IdentityError { Description = "Only duidaima.com email addresses are allowed" }); } return errors.Count == 0 ? IdentityResult.Success : IdentityResult.Failed(errors.ToArray()); } }在启动类添加用户验证服务,如下代码:
builder.Services.AddTransient<IUserValidator<AppUser>, CustomUsernameEmailPolicy>();现在我们测试一下该功能,打开浏览器,输入如下地址:https://localhost:7296/Admin/Create 并添加下面用户信息
[HttpPost] public async Task<IActionResult> Update(UpdateUserDTO updateUserDTO) { //堆代码 duidaima.com var appUser = await _userManager.FindByIdAsync(updateUserDTO.Id); if (appUser != null) { IdentityResult validEmail = null; if (!string.IsNullOrEmpty(updateUserDTO.Name) && !string.IsNullOrEmpty(updateUserDTO.Email)) { appUser.UserName = updateUserDTO.Name; appUser.Email = updateUserDTO.Email; validEmail = await _userValidator.ValidateAsync(_userManager, appUser); if (!validEmail.Succeeded) Errors(validEmail); } else ModelState.AddModelError("", "用户名和邮件不能为空"); IdentityResult validPass = null; if (!string.IsNullOrEmpty(updateUserDTO.Password)) { validPass = await _passwordValidator.ValidateAsync(_userManager, appUser, updateUserDTO.Password); if (validPass.Succeeded) appUser.PasswordHash = _passwordHasher.HashPassword(appUser, updateUserDTO.Password); else Errors(validPass); } else ModelState.AddModelError("", "密码不能为空"); if (!string.IsNullOrEmpty(updateUserDTO.Name) && !string.IsNullOrEmpty(updateUserDTO.Email) && !string.IsNullOrEmpty(updateUserDTO.Password) && validEmail.Succeeded && validPass.Succeeded) { var result = await _userManager.UpdateAsync(appUser); if (result.Succeeded) return RedirectToAction("Index"); else { foreach (IdentityError error in result.Errors) { ModelState.AddModelError("", error.Description); } } } } else ModelState.AddModelError("", "没有发现该用户"); return View(updateUserDTO); }在AdminController的构造函数中添加IPasswordValidator 和 IUserValidator引用
public class AdminController : Controller { private UserManager<AppUser> _userManager; private IPasswordHasher<AppUser> _passwordHasher; private IPasswordValidator<AppUser> _passwordValidator; private IUserValidator<AppUser> _userValidator; public AdminController(UserManager<AppUser> userManager, IPasswordHasher<AppUser> passwordHash, IPasswordValidator<AppUser> passwordValidator, IUserValidator<AppUser> userValidator ) { _userManager = userManager; _passwordHasher = passwordHash; _passwordValidator = passwordValidator; _userValidator = userValidator; } }我们再次更新一下用户,这是将显示如下错误: