【譯】MVC3 20個秘方-(6)找回忘記的密碼
問題
你網(wǎng)站的一個用戶在你的網(wǎng)站已經(jīng)注冊了,但是他忘記了密碼,現(xiàn)在需要一種方式去找回他。
解決方案
為了允許用戶去找回他們的密碼,必須在AccountController中添加一個新的action和一個新的view。這個功能將使用MemberShip類去尋找一個匹配的用戶,并發(fā)送一個包含它密碼的郵件到他們相關(guān)的郵箱。
討論
默認情況下,MVC Internet Applications 使用的是單向 hash為密碼加密。這樣,密碼不可能被找回。在下邊的例子。默認的加密方法使用雙向加密。這樣雖然不是很安全。但是他避免了強迫那些忘記了密碼的用戶重置密碼。
作為開始,我們首先要修改web.config中關(guān)于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>
上邊的代碼修改了4個關(guān)鍵的地方:
1. enablePasswordRetrieval 從false改true 。就是可以找回密碼。
2. enablePasswordReset was 從true改成false。就是不重置密碼。
3. 添加了passwordFormat="Encrypted" 。
4. machineKey 被生成了,用于加密。
在配置完config之后,我們要為Forgot Password view 創(chuàng)建一個model。這個類應(yīng)該放在AccountModel.cs類中。
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Web.Mvc;
using System.Web.Security;
namespace MvcApplication.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; }
}
}
在添加新的View之前,先build一下項目。展開View文件夾,右鍵點擊添加->視圖。命名為ForgotPassword。因為這個View將是一個強類型的,去對應(yīng)先前創(chuàng)建的ForgotPasswordModel。

再添加完View以后,在其中添加一個form。它接受用戶的Email地址。
@model MvcApplication.Models.ForgotPasswordModel
@{
ViewBag.Title = "ForgotPassword";
}
<h2>ForgotPassword</h2>
1.6 Retrieving a Forgotten Password | 27
<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>
}
然后更新在上一篇文章我們創(chuàng)建的MailClient class。添加一個新的函數(shù)。將為用戶發(fā)送他們忘記的密碼:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net.Mail;
using System.Net;
using System.Configuration;
namespace MvcApplication.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);
}
}
}
這個和前一個非常相似。除了多了第二個參數(shù)----用戶的密碼。密碼放在body中,發(fā)送給用戶。
最終,在這個AccountController中創(chuàng)建2個action。第一個簡單的讀取之前的view。第二個可以接收post的ForgotPasswordModel。用我們在form中收集到的Email地址,我們可以在Member數(shù)據(jù)庫中找到相應(yīng)user。然后發(fā)送密碼給那個email地址。
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 MvcApplication.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);
}
...
}
}
在最近的2個秘方中。基本的郵件已經(jīng)發(fā)送到用戶那去了。這些例子可以進一步提高成發(fā)送更復(fù)雜的郵件。甚至郵件內(nèi)容可以包括HTML。在Mail Message 類中有一個bool 類型的變量IsBodyHtml可以設(shè)置。是否支持發(fā)送HTML內(nèi)容。
另請參閱

浙公網(wǎng)安備 33010602011771號