如何在ASP.NET MVC中实现类似Gmail的注册邮箱验证码功能
在ASP.NET MVC中实现邮箱验证后完成注册的流程
1. 数据库设计(基于ASP.NET Identity扩展)
如果使用默认ASP.NET Identity身份验证框架,直接扩展IdentityUser类添加必要字段:
public class ApplicationUser : IdentityUser { // 标记用户是否已激活 public bool IsActive { get; set; } // 邮箱验证码 public string EmailVerificationCode { get; set; } // 验证码过期时间 public DateTime? VerificationCodeExpiry { get; set; } // 自定义个人信息字段 public string NickName { get; set; } }
更新数据库迁移,生成包含上述字段的用户表。
2. 初始注册流程
创建包含用户名、邮箱、密码、昵称等字段的注册视图,提交到AccountController的Register Action:
[HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task<ActionResult> Register(RegisterViewModel model) { if (ModelState.IsValid) { var user = new ApplicationUser { UserName = model.UserName, Email = model.Email, NickName = model.NickName, IsActive = false, // 初始状态设为未激活 VerificationCodeExpiry = DateTime.Now.AddMinutes(15) // 验证码15分钟过期 }; // 生成6位随机验证码 user.EmailVerificationCode = new Random().Next(100000, 999999).ToString(); // 将未激活用户存入数据库 var result = await UserManager.CreateAsync(user, model.Password); if (result.Succeeded) { await SendVerificationEmail(user); return RedirectToAction("VerifyEmail", "Account"); } AddErrors(result); } // 模型验证失败时返回注册页面 return View(model); }
3. 发送验证邮件
实现邮件发送逻辑,可使用SmtpClient或第三方库(如MailKit):
private async Task SendVerificationEmail(ApplicationUser user) { var verificationLink = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = user.EmailVerificationCode }, protocol: Request.Url.Scheme); var emailBody = $"请点击链接完成验证:<a href='{verificationLink}'>验证邮箱</a> " + $"或手动输入验证码:{user.EmailVerificationCode}"; var message = new MailMessage { From = new MailAddress("your-email@example.com"), Subject = "账号注册邮箱验证", Body = emailBody, IsBodyHtml = true }; message.To.Add(user.Email); using (var smtpClient = new SmtpClient("smtp.example.com", 587)) { smtpClient.Credentials = new NetworkCredential("your-email@example.com", "your-password"); smtpClient.EnableSsl = true; await smtpClient.SendMailAsync(message); } }
注意:生产环境中需将SMTP配置写入Web.config,避免硬编码账号密码。
4. 邮箱验证流程
提供两种验证方式:点击邮件链接或手动输入验证码,对应以下Action:
// 处理邮件链接跳转的GET请求 [HttpGet] [AllowAnonymous] public ActionResult ConfirmEmail(string userId, string code) { if (userId == null || code == null) return View("Error"); var user = UserManager.FindById(userId); if (user == null) return View("Error"); // 验证验证码有效性及过期时间 if (user.EmailVerificationCode == code && user.VerificationCodeExpiry > DateTime.Now) { // 激活用户并清空验证码相关字段 user.IsActive = true; user.EmailVerificationCode = null; user.VerificationCodeExpiry = null; UserManager.Update(user); return View("RegistrationSuccess"); } return View("InvalidVerificationCode"); } // 处理手动输入验证码的POST请求 [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task<ActionResult> VerifyEmail(VerifyEmailViewModel model) { if (ModelState.IsValid) { var user = await UserManager.FindByEmailAsync(model.Email); if (user != null && user.EmailVerificationCode == model.Code && user.VerificationCodeExpiry > DateTime.Now) { user.IsActive = true; user.EmailVerificationCode = null; user.VerificationCodeExpiry = null; await UserManager.UpdateAsync(user); return RedirectToAction("RegistrationSuccess", "Account"); } ModelState.AddModelError("", "验证码无效或已过期"); } return View(model); }
5. 限制未激活用户登录
修改登录逻辑,添加账号激活状态检查:
[HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task<ActionResult> Login(LoginViewModel model, string returnUrl) { if (ModelState.IsValid) { var user = await UserManager.FindByNameAsync(model.UserName); if (user != null) { if (!user.IsActive) { ModelState.AddModelError("", "账号尚未激活,请检查邮箱完成验证"); return View(model); } var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false); switch (result) { case SignInStatus.Success: return RedirectToLocal(returnUrl); case SignInStatus.LockedOut: return View("Lockout"); case SignInStatus.RequiresVerification: return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe }); case SignInStatus.Failure: default: ModelState.AddModelError("", "无效的登录尝试"); return View(model); } } ModelState.AddModelError("", "无效的登录尝试"); return View(model); } return View(model); }
6. 可选:重新发送验证码
添加重新发送功能,方便用户在验证码过期后获取新码:
[HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task<ActionResult> ResendVerificationCode(string email) { var user = await UserManager.FindByEmailAsync(email); if (user != null && !user.IsActive) { user.EmailVerificationCode = new Random().Next(100000, 999999).ToString(); user.VerificationCodeExpiry = DateTime.Now.AddMinutes(15); await UserManager.UpdateAsync(user); await SendVerificationEmail(user); return Json(new { success = true, message = "验证码已重新发送,请检查邮箱" }); } return Json(new { success = false, message = "该邮箱未注册或已激活" }); }
内容的提问来源于stack exchange,提问作者Cypher
相关产品推荐
相关产品推荐

