本文内容
本文档是VisualBasic教程(转至VisualC#教程)
ASP.NET有两个Web控件可拿来寻回和修改密码。PasswordRecovery控件能帮用户寻回他所遗失的密码。ChangePassword控件容许用户修改密码。与我们在本系列教程学校过的其他与登陆有关的Web控件类似,要重设和修改用户密码,须要PasswordRecovery和ChangePassword控件与后台的Membership框架协同工作。
简介
我和大多数人一样,在工行、公共事业公司、电话公司、电子邮箱网站和个人网站上,都有好多不同的密码要记住。既然有那么多秘密要存在脑袋里,人们忘掉密码也就不足为怪了。为解决该问题,提供用户账户的网站须要提供一种方法,让用户才能寻回自己的密码。一个典型的处理办法,是生成一个新的、随机的密码并通过电子短信发到存档的用户邮箱里。收到新密码后,多数用户将返回网站,将随机生成的密码修改为一个更容易记忆的密码。
ASP.NET有两个Web控件可拿来寻回和修改密码。PasswordRecovery控件能帮用户寻回他所遗失的密码。ChangePassword控件容许用户修改密码。与我们在本系列教程学校过的其他与登陆有关的Web控件类似,要重设和修改用户密码,须要PasswordRecovery和ChangePassword控件与后台的Membership框架协同工作。
本教程中,我们将阐述怎样使用这两个控件。我们还将了解怎样使用MembershipUser类的ChangePassword和ResetPassword方式帅同网 改密码 参数错误,通过编码修改和重设用户密码的。
步骤1:帮助用户寻回遗失的密码
所有支持用户账户的网站都须要向用户提供某种机制,让她们寻回忘记的密码。好消息是在ASP.NET中实现这样的功能是一件轻而易举的事,由于我们有PasswordRecoveryWeb控件。PasswordRecovery控件呈现一个界面,让用户提供用户名;假如须要的话,还要提供对她们的安全性问题的答案。之后,将用户密码用电子短信发到她们的邮箱里。
注意:由于电子短信是通过联通用纯文本格式发送的,所以用电子短信发送密码存在一定的安全性危险。
PasswordRecovery控件包含三个界面:
PasswordRecovery控件所显示的界面和执行的操作,与下述Membership的配置有关:
Membership框架的RequiresQuestionAndAnswer设置表示,用户在注册账户时是否必须指定安全性问题和答案。我们在《创建用户账户》教程中曾讨论过,假如RequiresQuestionAndAnswer为True(默认值),则CreateUserWizard的界面上有TextBox控件,供新用户输入安全性问题和答案;假如RequiresQuestionAndAnswer为False,则不搜集这方面的信息。与此类似,假如RequiresQuestionAndAnswer为True,PasswordRecovery控件则在输入用户名以后显示Question界面;只有当用户输入了正确的安全性答案以后,才才能寻回密码。但若果RequiresQuestionAndAnswer是False,PasswordRecovery控件就从UserName界面直接跳到Success界面。
当用户提供了他的用户名(或提供了他的用户名安全性答案,假如RequiresQuestionAndAnswer为True)之后,PasswordRecovery就通过电子电邮向用户发送他的密码。假如EnablePasswordRetrieval选项设置为True,就用电子电邮向用户发送他当前的密码。假如它设的是False并且EnablePasswordReset设的是True,则PasswordRecovery控件就为用户生成一个新的随机密码,并通过电子电邮将新密码发送给他。假如EnablePasswordRetrieval和EnablePasswordReset都设置为False,PasswordRecovery控件就抛出一个异常信息。
注意:回想一下,SqlMembershipProvider储存用户密码是用以下三种格式之一:明文、哈希(默认)或加密。采用哪种储存格式,取决于Membership的配置;我们的示范应用程序采用哈希密码格式。当使用哈希密码格式时,EnablePasswordRetrieval选项必须设为False,由于系统难以辨识存在数据库里的哈希格式的用户的实际密码。
图1说明了Membership的配置是如何影响PasswordRecovery的界面和操作的。
图1:RequiresQuestionAndAnswer、EnablePasswordRetrieval和EnablePasswordReset影响PasswordRecovery控件的界面和操作(单击此处查看实际大小的图象)
注意:在《在SQLServer中创建MembershipSchema》教程中,我们曾这样配置Membership提供者:设RequiresQuestionAndAnswer为True,EnablePasswordRetrieval为False,以及EnablePasswordReset为True。
使用PasswordRecovery控件
如今,我们看一下在一个ASP.NET页面上怎么使用PasswordRecovery控件。打开RecoverPassword.aspx页面,将一个PasswordRecovery控件从ToolBox拖到设计器中;将其ID设置为RecoverPwd。像Login和CreateUserWizardWeb控件一样,PasswordRecovery控件呈现的界面相当丰富:由Label、TextBox、Button和验证控件组成。您可以通过设置控件的风格属性,或将界面转化为模板来订制界面的外型。我将这项工作留给有兴趣的读者作为练习。
用户访问该页面后,先输入用户名并单击Submit按键。由于我们早已在Membership配置中设RequiresQuestionAndAnswer属性为True,所以这时PasswordRecovery控件就将显示Question界面。当用户输入了正确的安全性答案并单击了Submit后,PasswordRecovery控件就将用户密码改为一个随机生成的密码,并通过电子短信发送到存档的用户邮箱。并不须要我们写一行代码就可以做到所有那些!
在测试本页面之前,还有最后一项配置:须要在Web.config里指定短信发送设置。PasswordRecovery控件按照这种设置发送电子电邮。
短信发送配置在元素的元素食指定。用元素表示发送方式和默认的发件人(From)地址。以下的标记配置电邮设置:在端口25使用名为smtp.example.com的网路SMTP服务器,用户名和密码使用username/password凭据。
注意:是根元素的子元素帅同网 改密码 参数错误,是的同层元素。所以,不要将放在元素之内,而要将它放在同一层次上。
...
不仅使用一个网路SMTP服务器以外,作为可选设置,还可以指定一个分拣目录,在其中储存打算发送的电子电邮信息。
在做好这种SMTP配置后,通过浏览器访问RecoverPassword.aspx页面。首先,试着输入一个在用户库里没有的用户名。如图2所示,PasswordRecovery控件显示一条错误信息,强调未能找到该用户。信息的文本可以通过该控件的UserNameFailureText属性订制。
图2:假如输入无效的用户名,则显示错误信息(单击此处查看实际大小的图象)
如今输入一个用户名。请使用系统中确实有的一个账户的用户名,但是您可以访问该用户的邮箱,并晓得安全性答案。在输入了用户名并单击Submit后,PasswordRecovery控件显示Question界面。与在UserName界面中一样,倘若您输入了不正确的答案,PasswordRecovery控件就显示一条错误信息(见图3)。用QuestionFailureText属性订制该错误信息。
图3:假如用户输入了不正确的安全性答案,则显示一条错误信息(单击此处查看实际大小的图象)
最后,输入正确的安全性答案并单击Submit。在后台,PasswordRecovery控件生成一个随机的密码并将其分配给用户账户,通过电子电邮将新密码通知该用户(见图4),并显示Success界面。
图4:用户收到新密码的电子电邮(单击此处查看实际大小的图象)
订制电子电邮
PasswordRecovery控件发送的默认的电子电邮方式相当乏味(见图4)。电邮是由元素所规定的账户发出,主题为“Password”,短信内容为纯文本格式:
Pleasereturntothesiteandloginusingthefollowinginformation.(请返回网站,使用下述信息登陆)
UserName(用户名):username
Password(密码):password
可以使用PasswordRecovery控件的SendingMail风波的一个风波处理程序,通过编码订制该短信,或则使用MailDefinition属性通过申明订制。下边,我们阐述一下这两种方式。
SendingMail风波在短信发送之前迸发,这是我们通过程序调整电邮信息的最后机会。当该风波迸发后,风波处理程序传递一个MailMessageEventArgs类型的对象,其Message属性包含一个打算发送的电子短信的引用。
为SendingMail风波创建一个风波处理程序,并加入以下代码(通过编码将webmaster@example.com加到抄送(CC)列表中)。
Protected Sub RecoverPwd_SendingMail(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.MailMessageEventArgs)
Handles RecoverPwd.SendingMail
e.Message.CC.Add("webmaster@example.com")
End Sub
也可以通过申明配置电邮信息。PasswordRecovery的MailDefinition属性是一个MailDefinition类型的对象,MailDefinition类提供与电子电邮相关的属性的寄主,包括From、CC、Priority、Subject、IsBodyHtml、BodyFileName等。考虑到用户可能是菜鸟,最好将Subject属性写得比默认设置(“Password”)更详尽一些,如写为“Yourpasswordhasbeenreset...”(“您的密码已被重置...”)。
要订制电邮的内容,我们须要创建一个单独的电邮模板文件,其中包含电邮内容。首先在网站中创建一个新的文件夹,命名为EmailTemplates。之后,加入一个新文件到该文件夹中,起名为PasswordRecovery.txt,并在其中加入以下内容:
Your password has been reset, <%UserName%>!
According to our records, you have requested that your password be reset. Your new
password is: <%Password%>
If you have any questions or trouble logging on please contact a site administrator.
Thank you!
注意其中使用了占位符和。PasswordRecovery控件在发送短信之前,会手动将这两个占位符替换为用户名和重置的密码。
最后,将MailDefinition的BodyFileName属性设置为我们刚才创建的电子电邮模板(~/EmailTemplates/PasswordRecovery.txt)。
在做完这种修改后,重新访问RecoverPassword.aspx页,并输入您的用户名和安全性答案。您收到的电邮应当如图5所示。注意电邮还抄送到webmaster@example.com,并且主题和内容早已更新了。
图5:电邮的主题、内容和抄送列表早已更新了(单击此处查看实际大小的图象)
假如要发送一个HTML格式的电邮,则要设置IsBodyHtml为True(默认是False),并修改电子电邮模板,使之包括HTML。
MailDefinition并不是PasswordRecovery类特有的属性。我们将在步骤2中见到,ChangePassword控件也提供了一个MailDefinition属性。据悉,CreateUserWizard控件有一个属性,能配置为自动向新用户发送一个欢迎电邮。
注意:目前,两侧导航条中并没有到RecoverPassword.aspx页的这一项。只有当用户不能正常登陆到网站时,他就会访问此页。所以要修改Login.aspx页,使其包含一个到RecoverPassword.aspx页的链接。
通过编码重置用户密码
当重置用户密码时,PasswordRecovery控件调用MembershipUser对象的ResetPassword方式。该方式有两个重载:
这两个重载都返回一个新的随机生成的密码。
像Membership框架中的其他方式一样,ResetPassword方式委托给配置的提供者。SqlMembershipProvider调用aspnet_Membership_ResetPassword储存过程,传送用户的用户名、新密码和用户提供的密码答案等数组。该储存过程确认密码答案相匹配后,修改用户密码。
低层施行的两个注意事项:
阐述随机密码是怎样生成的
图4和图5所示的电邮中,随机生成的密码是由Membership类的GeneratePassword方式创建的。该方式接收两个整数输入参数length和numberOfNonAlphanumericCharacters,并返回一个字符串,该字符串起码length个字符长,起码有numberOfNonAlphanumericCharacters个非字母数字字符。当从Membership类或与登陆相关的Web控件内调用该方式时,这两个参数的值便由Membership配置的MinRequiredPasswordLength和MinRequiredNonalphanumericCharacters属性确定了,我们将它们分别设置为7和1。
GeneratePassword方式使用一个加密强随机数生成器,保证在选择随机字符时没有偏向性。据悉,GeneratePassword是公用的,也就是当您须要生成随机字符串或密码时,可以在ASP.NET应用程序中直接使用它。
注意:SqlMembershipProvider类生成的随机密码总是起码14个字符长,所以假如MinRequiredPasswordLength大于14,则该值被忽视。
步骤2:修改密码
随机生成的密码不容易记住。看一下显示在图4中密码:WWGUZv(f2yM:Bd。试着将它记到脑袋里!不用说,当用户收到这样的一个随机生成的密码后,他肯定想修改密码,改成一个容易记忆的。
用ChangePassword控件为用户创建一个修改密码的界面ChangePassword控件很像PasswordRecovery控件,包括两个界面:ChangePassword和Success。ChangePassword界面让用户输入旧密码和新密码。当用户输入的旧密码正确无误,新密码满足最小宽度和最少非字母数字字符的要求时,ChangePassword控件修改用户密码并显示Success界面。
注意:ChangePassword控件通过调用MembershipUser对象的ChangePassword方式修改用户密码。ChangePassword方式接收两个String输入参数:oldPassword和newPassword;假如oldPassword正确,则用newPassword更新用户账户。
打开ChangePassword.aspx页并向页中添加一个ChangePassword控件,命名为ChangePwd。这时Design窗口应当显示的是ChangePassword界面(见图6)。像PasswordRecovery控件一样,您可以通过控件的智能标记切换界面。据悉,可以通过各类风格属性调配或将它们转化为模板,订制这种界面的外型。
图6:假如用户输入了不正确的密码,则显示错误信息(单击此处查看实际大小的图象)
ChangePassword控件才能更新当前登入用户的密码或另一个指定用户的密码。如图6所示,默认的ChangePassword界面中只有三个TextBox控件:一个用于输入旧密码,两个用于输入新密码。这个默认的界面用于修改当前已登陆用户的密码。
要用ChangePassword控件修改另一个用户的密码,将控件的DisplayUserName属性设置为True。这样就向页面中加进了第四个TextBox,用于输入待修改密码的用户的用户名。
将DisplayUserName设置为True可以让退出登入的用户毋须登陆才能修改密码。但我觉得,要求用户在修改密码之前先登入,这也是无可诟病的。所以,保留DisplayUserName的设置为False(默认值)。但是做这个决定本身,说明我们实质上是严禁匿名用户访问本页的。更新本站点的URL授权规则,拒绝匿名用户访问ChangePassword.aspx页面。假如您对URL授权规则的复句不大熟悉了,请返回备考《基于用户的授权》教程。
注意:乍看上去,DisplayUserName属性可以拿来让管理员修改其他用户的密码。并且,虽然DisplayUserName设为True,也必需要晓得并输入正确的旧密码。我们将在步骤3讨论由管理员修改用户密码的方式。
通过浏览器访问ChangePassword.aspx页面,并修改您的密码。请注意,当您输入的新密码没有满足在Membership中规定的密码宽度和非字母数字字符要求时,将显示一个错误信息(见图7)。
图7:假如用户输入了不正确的密码,则显示错误信息(单击此处查看实际大小的图象)
在输入了正确的旧密码和有效的新密码后,就将修改登陆用户的密码,并显示Success界面。
发送确认电子电邮
默认情况下,ChangePassword控件并不发送短信给刚才修改了密码的用户。假如您想发送一个电邮,则设置该控件的MailDefinition属性即可。如今让我们配置ChangePassword控件,向用户发送一个HTML格式的电邮,其中包含她们的新密码。
首先在EmailTemplates文件夹里创建一个新文件,名为ChangePassword.htm。并添加以下标记:
Your Password Has Been Changed!
This email confirms that your password has been changed.
To log on to the site, use the following credentials:
Username:
<%UserName%>
Password:
<%Password%>
If you have any questions or encounter any problems logging in,
please contact a site administrator.
之后,将ChangePassword控件的MailDefinition属性中的BodyFileName、IsBodyHtml和Subject属性分别设置为“~/EmailTemplates/ChangePassword.htm”、True和“Yourpasswordhasbeenchanged!”(您修改了密码!)
做完这种改动后,重新访问该页面并再度修改密码。这一次,ChangePassword控件发送一个订制的HTML格式的电邮到用户的邮箱里(见图8)。
图8:向用户通知密码已修改的短信(单击此处查看实际大小的图象)
步骤3:容许管理员修改用户密码
支持用户账户的应用程序的一个普通特点,是才能让管理员修改其他用户的密码。有时须要有该功能,是由于系统没有提供让用户修改自己密码的功能。在这些情况下,用户想寻回她们遗忘的密码的惟一方式,就是请管理员给她们分配一个新密码。但是,有了PasswordRecovery和ChangePassword控件后,管理员不再须要疏于为用户修改密码了,由于用户才能自己来做这件事。
然而,假若您的顾客坚持管理员必须才能修改其他用户的密码如何办?不幸的是,要降低该功能我们必须付出一点辛酸。由于要修改一个用户的密码,MembershipUser对象的ChangePassword方式要求必须提供旧密码和新密码,并且管理员要修改一个用户的密码并不一定晓得他的密码。
一个变通方案是先重设用户密码,之后修改它为新密码;使用下述代码:
Dim usr As MembershipUser = Membership.GetUser(username)
Dim resetPwd As String = usr.ResetPassword()
usr.ChangePassword(resetPwd, newPassword)
这段代码首先检索username信息,管理员打算修改该用户的密码。之后,调用ResetPassword方式,它分配给该用户一个新的随机密码。该方式返回随机生成的密码,并保存在resetPwd变量中。如今我们晓得该用户的密码了,就能否通过调用ChangePassword来修改它了。
但是,只有在Membership系统配置中RequiresQuestionAndAnswer设为False时,这段代码能够有效运行。假如RequiresQuestionAndAnswer是True,如同我们的应用程序一样,这么ResetPassword方式就须要传递安全性答案,否则将会抛出一个异常信息。
假如Membership框架配置为要求安全性问题和答案,而您的顾客又坚持管理员必须才能修改用户密码,您有三个可选方案:
前面三个方案无论那个都谈不上非常完满,但有时侯程序员的生活就是这个样子。
我采用的是上述第三种方案,写代码绕开Membership和MembershipUser类直接操作SecurityTutorials数据库。
注意:倘若直接操作数据库,Membership框架所提供的封装都会显得非常零乱。并且这样做我们必须与SqlMembershipProvider打交道,使我们的代码不再这么简明。据悉,这种代码还不一定能在ASP.NET之后的版本下工作,由于Membership框架有可能做改动。该方案是一个变通方案,并且像多数变通方案一样,是不完美的。
这部份代码相当繁杂和繁琐。所以,我不准备在本教程对它做深入的阐述了。倘若您想对此做更多的了解,可以下载本教程的代码并访问~/Administration/ManageUsers.aspx页面。该页面是我们在前一篇教程中构建的,它列举了每位用户。我修改了那儿面的GridView,使之包含一个到UserInformation.aspx页的链接,通过查询字符串传递所选用户的用户名。UserInformation.aspx页面列举了所选用户的信息,并包括几个修改密码用的TextBox(见图9)。
输入新密码后,在第二个TextBox中确认它,之后单击UpdateUser按键,这将引起一个回传并调用aspnet_Membership_SetPassword储存过程,更新用户密码。我建议这些对该功能感兴趣的读者,要愈发熟悉其中的代码并试着做些扩充,降低一个向修改了密码的用户发送短信的功能。
图9:管理员可以修改用户的密码(单击此处查看实际大小的图象)
注意:目前,只有Membership框架配置为储存明文或哈希格式的密码时,UserInformation.aspx页面能够正常工作。我没有编撰代码用加密格式对新密码加密,但我约请您来平添该功能。我建议在所要写的代码中采用这些方式:用一个像Reflector这样的反编译工具,检测.NETFramework中技巧的源代码;首先检测SqlMembershipProvider类的ChangePassword方式。这是我写代码创建密码的哈希值时所用的方法。
小结
ASP.NET提供了两个控件帮助用户管理她们的密码。PasswordRecovery控件为遗忘了密码的用户提供帮助。按照Membership框架的配置,向用户发送短信,或是告知她们现有的密码,或是告知一个新的随机生成的密码。ChangePassword控件使用户才能修改她们的密码。
像Login和CreateUserWizard控件一样,PasswordRecovery和ChangePassword控件呈现了丰富的用户界面,何必编撰一条申明标记或一行代码。假如默认的用户界面不能满足您的须要,您可以通过各类风格属性订制界面。另一个可选方式是,可以将控件的界面转换为模板,使控件更为精巧。这种控件在后台使用MembershipAPI,调用MembershipUser对象的ResetPassword和ChangePassword技巧。
快乐编程!