如何在ASP.NET Core Identity中实现用户名注册登录(保留邮箱收集)
实现ASP.NET Core Identity 用户名+密码登录(同时保留邮箱收集)
1. 调整注册流程:同时收集用户名与邮箱
1.1 修改注册ViewModel(RegisterViewModel)
默认模板的RegisterViewModel通常只有邮箱、密码相关字段,需要添加用户名属性并配置验证规则:
public class RegisterViewModel { [Required] [Display(Name = "用户名")] [StringLength(256, ErrorMessage = "{0} 长度至少为 {2} 个字符。", MinimumLength = 3)] public string UserName { get; set; } [Required] [EmailAddress] [Display(Name = "邮箱")] public string Email { get; set; } [Required] [StringLength(100, ErrorMessage = "{0} 长度至少为 {2} 个字符。", MinimumLength = 6)] [DataType(DataType.Password)] [Display(Name = "密码")] public string Password { get; set; } [DataType(DataType.Password)] [Display(Name = "确认密码")] [Compare("Password", ErrorMessage = "密码与确认密码不匹配。")] public string ConfirmPassword { get; set; } }
1.2 更新注册视图(Register.cshtml)
在原有邮箱输入框前插入用户名输入区域,保留原有的邮箱、确认密码等字段:
<div class="form-group"> <label asp-for="UserName"></label> <input asp-for="UserName" class="form-control" /> <span asp-validation-for="UserName" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Email"></label> <input asp-for="Email" class="form-control" /> <span asp-validation-for="Email" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Password"></label> <input asp-for="Password" class="form-control" /> <span asp-validation-for="Password" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="ConfirmPassword"></label> <input asp-for="ConfirmPassword" class="form-control" /> <span asp-validation-for="ConfirmPassword" class="text-danger"></span> </div>
1.3 修改注册Post方法(AccountController/Register)
创建用户时同时赋值UserName和Email,避免默认用邮箱填充用户名的逻辑:
[HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task<IActionResult> Register(RegisterViewModel model) { if (ModelState.IsValid) { // 手动初始化用户实体,分别设置用户名与邮箱 var user = new IdentityUser { UserName = model.UserName, Email = model.Email }; var result = await _userManager.CreateAsync(user, model.Password); if (result.Succeeded) { // 保留原有后续逻辑(如邮箱确认、自动登录等) await _signInManager.SignInAsync(user, isPersistent: false); return RedirectToAction(nameof(HomeController.Index), "Home"); } foreach (var error in result.Errors) { ModelState.AddModelError(string.Empty, error.Description); } } // 验证失败返回注册页 return View(model); }
2. 调整登录流程:使用用户名+密码验证
2.1 修改登录ViewModel(LoginViewModel)
将原有的Email字段替换为UserName:
public class LoginViewModel { [Required] [Display(Name = "用户名")] public string UserName { get; set; } [Required] [DataType(DataType.Password)] [Display(Name = "密码")] public string Password { get; set; } [Display(Name = "记住我?")] public bool RememberMe { get; set; } }
2.2 更新登录视图(Login.cshtml)
把邮箱输入框替换为用户名输入框:
<div class="form-group"> <label asp-for="UserName"></label> <input asp-for="UserName" class="form-control" /> <span asp-validation-for="UserName" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Password"></label> <input asp-for="Password" class="form-control" /> <span asp-validation-for="Password" class="text-danger"></span> </div> <div class="form-group"> <div class="checkbox"> <label asp-for="RememberMe"> <input asp-for="RememberMe" /> @Html.DisplayNameFor(m => m.RememberMe) </label> </div> </div>
2.3 修改登录Post方法(AccountController/Login)
调用PasswordSignInAsync时传入用户名而非邮箱:
[HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null) { ViewData["ReturnUrl"] = returnUrl; if (ModelState.IsValid) { // 使用用户名执行登录验证 var result = await _signInManager.PasswordSignInAsync( model.UserName, model.Password, model.RememberMe, lockoutOnFailure: true ); if (result.Succeeded) { return LocalRedirect(returnUrl ?? Url.Content("~/")); } if (result.RequiresTwoFactor) { return RedirectToAction(nameof(LoginWith2fa), new { returnUrl, model.RememberMe }); } if (result.IsLockedOut) { return RedirectToAction(nameof(Lockout)); } else { ModelState.AddModelError(string.Empty, "无效的登录尝试。"); return View(model); } } // 验证失败返回登录页 return View(model); }
3. 额外注意事项
- 用户名唯一性验证:可在注册前手动检查用户名是否已存在,避免重复:
var existingUser = await _userManager.FindByNameAsync(model.UserName); if (existingUser != null) { ModelState.AddModelError("UserName", "该用户名已被使用。"); return View(model); } - 邮箱确认逻辑:原有邮箱确认流程无需修改,因为
Email字段已正确保存到用户实体中。 - 用户信息展示:后续页面若需显示用户名,直接调用
User.Identity.Name即可获取。
内容的提问来源于stack exchange,提问作者Massey
相关产品推荐
相关产品推荐

