[转载][翻译]ASP.NET MVC 3 开发的20个秘诀(六)[20 Recipes for Programming MVC 3]:找回忘记的密码 – O2DS – 博客园.
议题
您或者在您网站的注册的某个用户,无法想起自己的密码了,需要有一种方法能找回它。
解决方案
在AccountController控制器中添加一个新的动作和视图,以便用户可以找回他们的密码。利用Membership类搜索和匹配用户,并发送一个包含密码的电子邮件。
讨论
默认情况下,MVC Internet应用程序使用的是无法逆向转换的单向哈希算法。在下面的例子中,默认是双向散列加密方式。这种方式并不是很安全,但是在用户忘记密码时可以避免强迫用户修改密码。
先在Web.config文件中调整Membership节点的设置:
<?xml version="1.0"?> <configuration> ... <system.web> ... <membership> <providers> <clear /> <add name="AspNetSqlMembershipProvider" type= "System.Web.Security.SqlMembershipProvider" connectionStringName="ApplicationServices" enablePasswordRetrieval="true" enablePasswordReset= "false" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" passwordFormat= "Encrypted" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" /> </providers> </membership> <machineKey validationKey= "2CF9FF841A23366CFA5D655790D9308656B1F7532C0B95B5C067F80C45E59875 E2F3D68DAC63B5024C31D974D4BE151341FB8A31FC4BC3705DF5398B553FC3C3" decryptionKey="8E71407B62F47CCA3AAA6546B3880E1A0EF9833700 E0A0C511710F537E64B8B6" validation="SHA1" decryption="AES" /> ... </system.web> ... </configuration>
针对上面的设置代码,我们四个更改:
- 将enablePasswordRetrieval更改为True;
- 将enablePasswordReset更改为false;
- 添加passwordFormat=”Encrypted”;
- 生成加密的machineKey;
配置信息修改完毕后,在AccountModels.cs类中添加一个新的动作并创建忘记密码的视图:
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Globalization; using System.Web.Mvc; using System.Web.Security; namespace MvcApplication4.Models { public class ChangePasswordModel { ... } public class LogOnModel { ... } public class RegisterModel { ... } public class ForgotPasswordModel { [Required] [DataType(DataType.EmailAddress)] [Display(Name = "Email address")] public string Email { get; set; } } }
在创建新视图之前,应用程序必须先编译。单击“生成”->“生成解决方案”或按F6。编译完成之后,展开Views文件夹,右键单击 “Account”文件夹,选择“添加”->“视图”(如图1-4)。视图名称更改为“ForgotPassword”,选中“创建强类型视图”选 项,从“模型类”下拉框中选择先前创建的“ForgotPasswordModel”,然后点击“添加”。
视图创建后,添加一个基本的表单,表单接受用户输入注册时填写的电子邮件地址:
@model MvcApplication4.Models.ForgotPasswordModel @{ ViewBag.Title = "ForgotPassword"; } <h2>ForgotPassword</h2> <p> Use the form below to retrieve your password. </p> <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> @using (Html.BeginForm()) { @Html.ValidationSummary(true, "Password retrieval was unsuccessful. Please correct the errors and try again.") <div> <fieldset> <legend>Account Information</legend> <div class="editor-label"> @Html.LabelFor(m => m.Email) </div> <div class="editor-field"> @Html.TextBoxFor(m => m.Email) @Html.ValidationMessageFor(m => m.Email) </div> <p> <input type="submit" value="Retrieve Password" /> </p> </fieldset> </div> }
下面将在之前创建的MailClient类中添加一个新方法,以实现发送用户忘记的密码:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Net.Mail; using System.Net; using System.Configuration; namespace MvcApplication4.Utils { public class MailClient { private static readonly SmtpClient Client; static MailClient() { ... } private static bool SendMessage(string from, string to, string subject, string body) { ... } public static bool SendWelcome(string email) { ... } public static bool SendLostPassword(string email, string password) { string body = "Your password is: " + password; return SendMessage("no-reply@no-reply.com", email, "Lost Password", body); } } }
这个方法与上一个方法(*译者注:发送欢迎邮件的方法)十分相似,只是又添加了一个参数 — 用户的密码。这个密码将被添加到电子邮件的内容中并发送给用户。
最后在AccountController中添加两个ForgotPassword方法,第一个方法是默认载入时动作,第二是在用户填写完电子邮件地址后,接受回发数据的动作,他会从数据库中通过搜索并匹配电子邮件地址找到用户,然后将用户密码通过这个地址发给用户。
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; using System.Web.Security; using MvcApplication4.Models; using MvcApplication4.Utils; namespace MvcApplication4.Controllers { public class AccountController : Controller { ... // // Get: /Account/ForgotPassword public ActionResult ForgotPassword() { return View(); } // // Post: /Account/ForgotPassword [HttpPost] public ActionResult ForgotPassword( ForgotPasswordModel model) { if (ModelState.IsValid) { MembershipUserCollection users = Membership.FindUsersByEmail(model.Email); if (users.Count > 0) { foreach (MembershipUser user in users) { MailClient.SendLostPassword(model.Email, user.GetPassword()); } return RedirectToAction("LogOn"); } } // If we got this far, something failed, // redisplay form return View(model); } ... } }
在之前的两个秘诀中,只是给用户发送了一些基本信息。将MailMessage的isBodyHtml设置为True,通过简单的扩展增强就可以发送HTML或者更复杂的内容给用户。
参考