asp.net mvc使用邮箱找回密码功能的详细步骤

来源:互联网 发布:手机改图软件 编辑:程序博客网 时间:2024/06/05 12:50

背景条件:

使用的是asp.net mvc6 ,Microsoft.AspNet.Identity

如果没用Microsoft.AspNet.Identity,那这篇文章对你帮助不大。

设计步骤:

1、输入注册邮箱页面

2、验证邮箱在用户表中是否存在,如果存在,则会向用户邮箱发送一重置密码的链接,并且跳转到忘记密码确认页面。如果不存在,考虑到安全,不会提示该邮箱不存在,仍然会跳转到忘记密码确认页面,但是不会向邮箱发送邮件。

3、用户打开自己的邮箱,点击重置密码链接,跳转到重置密码页面重新设置密码

4、在重置密码页面输入新密码和确认密码,点重置按钮,重置成功后跳转到重置确认页面

一、首先是忘记密码页面


很简单,就一个电子邮件输入框,一个发送邮件按钮。

这个电子邮箱是你注册时填写的邮箱,胡乱填写个邮箱是没有用的

点发送邮件按钮。然后执行action动作。

[HttpPost]        [AllowAnonymous]        [ValidateAntiForgeryToken]        public async Task<ActionResult> ForgotPassword(ForgotPasswordViewModel model)        {            if (ModelState.IsValid)            {                var user = await UserManager.FindByIdAsync(model.Email);                //EventLog.WriteLog("" + (user == null));                //if (user == null || !(await UserManager.IsEmailConfirmedAsync(user.Id)))                if (user == null)                {                    //EventLog.WriteLog("该邮箱不存在或者未经确认");                    // 请不要显示该用户不存在或者未经确认                    return View("ForgotPasswordConfirmation");                }                // 有关如何启用帐户确认和密码重置的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkID=320771                // 发送包含此链接的电子邮件                string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);                if (Request.Url != null)                {                    var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);                    //根据user.id获取到该会员的email,然后调用await this.EmailService.SendAsync(message).WithCurrentCulture()完成邮件发送                    //UserManager.SendEmailAsync是一个虚方法                    await UserManager.SendEmailAsync(user.Id, "重置密码", "请通过单击 <a href=\"" + callbackUrl + "\">此处</a>来重置你的密码");                }                return RedirectToAction("ForgotPasswordConfirmation", "Account");            }            // 如果我们进行到这一步时某个地方出错,则重新显示表单            return View(model);        }


UserManager.FindByEmailAsync此方法是通过email在会员表中搜索是否有符合条件的记录。如果没有,跳转到ForgotPasswordConfirmation.cshtml页面。

如果用户存在,则使用UserManager.GeneratePasswordResetTokenAsync生成一个重设密码的token。然后用Url.Action方法拼接一个链接串,再调用
UserManager.SendEmailAsync向邮箱中发送一封带重置密码链接的邮件。发送完后用RedirectToAction("ForgotPasswordConfirmation""Account")
方法跳转到忘记密码确认页面。
二、忘记密码确认页面内容如下:

注意此方法:UserManager.SendEmailAsync,这个方法是发邮件的方法。但是如何设置才能使系统自动发送邮件还需要相应的类来实现。首先我们反编译这个方法,他在Microsoft.AspNet.Identity.Core.dll中

public virtual async Task SendEmailAsync(TKey userId, string subject, string body){this.ThrowIfDisposed();if (this.EmailService != null){IdentityMessage message = new IdentityMessage{Destination = await this.GetEmailAsync(userId).WithCurrentCulture<string>(),Subject = subject,Body = body};await this.EmailService.SendAsync(message).WithCurrentCulture();}}

在这个反编译代码中,注意this.EmailService,这个EmailService类需要自定义,这个类中的SendAsync方法要自己实现,以便使用特定的邮箱发邮件。它需要继承IIdentityMessageService,代码如下:

public class EmailService : IIdentityMessageService    {        public async Task SendAsync(IdentityMessage message)        {            MailConfig mailConfig = (MailConfig)ConfigurationManager.GetSection("application/mail");            if (mailConfig.RequireValid)            {                if (1 == 0)                {                    EventLog.WriteLog(mailConfig.EmailAddress);                    EventLog.WriteLog(mailConfig.EmailUserName);                    EventLog.WriteLog(message.Destination);                }                // 设置邮件内容                var mail = new MailMessage(                    new MailAddress(mailConfig.EmailAddress, mailConfig.EmailUserName),                    new MailAddress(message.Destination)                    );                mail.Subject = message.Subject;                mail.Body = message.Body;                mail.IsBodyHtml = true;                mail.BodyEncoding = Encoding.UTF8;                // 设置SMTP服务器                var smtp = new SmtpClient(mailConfig.SmtpServer, mailConfig.SmtpPort);                smtp.UseDefaultCredentials = false;                smtp.Credentials = new System.Net.NetworkCredential(mailConfig.EmailAddress, mailConfig.EmailPwd);                smtp.DeliveryMethod = SmtpDeliveryMethod.Network;                await smtp.SendMailAsync(mail);            }            await Task.FromResult(0);        }    }

在这里面使用了MailConfig类。代码如下:

public class MailConfig : ConfigurationSection    {        /// <summary>        /// 注册时是否需要验证邮箱        /// </summary>        [ConfigurationProperty("RequireValid", DefaultValue = "false", IsRequired = true)]        public bool RequireValid        {            get            {                 return (bool)this["RequireValid"];            }            set            {                this["RequireValid"] = value;            }        }        /// <summary>        /// SMTP服务器        /// </summary>        [ConfigurationProperty("SmtpServer", IsRequired = true)]        public string SmtpServer        {            get            {                return (string)this["SmtpServer"];            }            set            {                this["SmtpServer"] = value;            }        }        /// <summary>        /// 默认端口25(设为-1让系统自动设置)        /// </summary>        [ConfigurationProperty("SmtpPort", DefaultValue = "25", IsRequired = true)]        public int SmtpPort        {            get            {                return (int)this["SmtpPort"];            }            set            {                this["SmtpPort"] = value;            }        }        /// <summary>        /// 地址        /// </summary>        [ConfigurationProperty("EmailAddress", IsRequired = true)]        public string EmailAddress        {            get            {                return (string)this["EmailAddress"];            }            set            {                this["EmailAddress"] = value;            }        }        /// <summary>        /// 账号        /// </summary>        [ConfigurationProperty("EmailUserName", IsRequired = true)]        public string EmailUserName        {            get            {                return (string)this["EmailUserName"];            }            set            {                this["EmailUserName"] = value;            }        }        /// <summary>        /// 密码        /// </summary>        [ConfigurationProperty("EmailPwd", IsRequired = true)]        public string EmailPwd        {            get            {                return (string)this["EmailPwd"];            }            set            {                this["EmailPwd"] = value;            }        }        /// <summary>        /// 是否使用SSL连接        /// </summary>        [ConfigurationProperty("EnableSSL", DefaultValue = "false", IsRequired = false)]        public bool EnableSSL        {            get            {                return (bool)this["EnableSSL"];            }            set            {                this["EnableSSL"] = value;            }        }        /// <summary>        ///         /// </summary>        [ConfigurationProperty("EnablePwdCheck", DefaultValue = "false", IsRequired = false)]        public bool EnablePwdCheck        {            get            {                return (bool)this["EnablePwdCheck"];            }            set            {                this["EnablePwdCheck"] = value;            }        }    }

web.config中相关的email配置:

<application>
    <mail RequireValid="true" SmtpServer="smtp.exmail.qq.com" SmtpPort="25" EmailUserName="你的名字" EmailAddress="xxx@xx.xxx" EmailPwd="xxx" EnableSSL="false" EnablePwdCheck="false" />
</application>

至此,发邮件的相关类及方法已经介绍完了。

三、去电子邮箱查收重置密码邮件


四、打开邮箱中的邮件,点击此处链接。跳转到重置密码页面


再次输入你的邮箱,然后输入新密码及新密码确认。

相应的页面actionresult:

 [AllowAnonymous]        public ActionResult ResetPassword(string code, string userid)        {            return code == null ? View("Error") : View();        }

相应的model:

public class ResetPasswordViewModel    {        [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; }        public string Code { get; set; }        public string UserId { get; set; }    }

相应的cshtml代码,只摘一部分:

@model LMCMS.ViewModel.ResetPasswordViewModel@{    ViewBag.Title = "使用电子邮件重置密码";} <h2>@ViewBag.Title。</h2> @using (Html.BeginForm("ResetPassword""Account"FormMethod.Post, new { @class = "form-horizontal", role = "form" })){    @Html.AntiForgeryToken()    <h4>重置您的密码。</h4>    <hr />    @Html.ValidationSummary(""new { @class = "text-danger" })    @Html.HiddenFor(model => model.Code)    @Html.HiddenFor(Model=>Model.UserId)        <div class="form-group">        @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })        <div class="col-md-4 col-xs-8">            @Html.PasswordFor(m => m.Password, new { @class = "form-control" })        </div>    </div>    <div class="form-group">        @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" })        <div class="col-md-4 col-xs-8">            @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" })        </div>    </div>    <div class="form-group">        <div class="col-md-offset-2 col-md-10">            <input type="submit" class="btn btn-default" value="重置" />        </div>    </div>}
这里的隐藏字段model.Code及Model.UserId会自动接收url中相应的变量值。

点击重置按钮后相应的处理方法:

[HttpPost]        [AllowAnonymous]        [ValidateAntiForgeryToken]        public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)        {            if (!ModelState.IsValid)            {                return View(model);            }            //EventLog.WriteLog(model.Email);            var user = await UserManager.FindByEmailAsync(model.UserId);            //EventLog.WriteLog("" + (user == null));            if (user == null)            {                // 请不要显示该用户不存在                return RedirectToAction("ResetPasswordConfirmation", "Account");            }            var result = await UserManager.ResetPasswordAsync(user.Id, model.Code, model.Password);            if (result.Succeeded)            {                return RedirectToAction("ResetPasswordConfirmation", "Account");            }            AddErrors(result);            return View();        }

五、点击重置按钮,经过处理后,重置成功,则跳到重置密码确认页面


至此重置密码成功,可以使用新密码登录了


0 0
原创粉丝点击