在Membership编程的时候,通常会做到管理员给用户设置一个新密码的功能。然而,在MembershipProvider里,并没有提供相应的方法。
MembershipUser类虽然提供了一个ChangePassword的方法,其原型如下:
但是,怎么才能知道别人的oldPassword呢?
一开始的思路是,根据用户编号,把密码直接从数据库里读出来。然后,试试看能不能解密——汗一下现在,这个好像难度高了点儿*_^,别说是HASH的密码没法解,就是能解的密码,就我这小脑袋,花上几年也可能解不起来。
然后,就想通过Membership相关的控件来完成。VS2005的Login控件组里不是提供了一个ChangePassword控件么?把它的UserName给设置上,然后隐藏不显示不就能达到目的了么。果然,这样子达到了修改密码的目的,但是,却产生了一个严重的副作用:修改完此用户的密码后,Authentication的Cookie就被重写成修改了密码的用户的身份信息了。例如,我用管理员Admin修改了用户User1的密码,点了“完成”以后,我的角色就不再是管理员,而是“用户”,身份也从Admin变成了User1。这是让人不能容忍的。
于是再想办法。在MSDN上找到了一个叫ResetPassword()的方法,其原型:
MembershipUser类虽然提供了一个ChangePassword的方法,其原型如下:
public virtual bool ChangePassword (
string oldPassword,
string newPassword
)
string oldPassword,
string newPassword
)
但是,怎么才能知道别人的oldPassword呢?
一开始的思路是,根据用户编号,把密码直接从数据库里读出来。然后,试试看能不能解密——汗一下现在,这个好像难度高了点儿*_^,别说是HASH的密码没法解,就是能解的密码,就我这小脑袋,花上几年也可能解不起来。
然后,就想通过Membership相关的控件来完成。VS2005的Login控件组里不是提供了一个ChangePassword控件么?把它的UserName给设置上,然后隐藏不显示不就能达到目的了么。果然,这样子达到了修改密码的目的,但是,却产生了一个严重的副作用:修改完此用户的密码后,Authentication的Cookie就被重写成修改了密码的用户的身份信息了。例如,我用管理员Admin修改了用户User1的密码,点了“完成”以后,我的角色就不再是管理员,而是“用户”,身份也从Admin变成了User1。这是让人不能容忍的。
于是再想办法。在MSDN上找到了一个叫ResetPassword()的方法,其原型:
1 public virtual string ResetPassword ()
根据MSDN上的说明,它为一个用户重置一个新的、自动生成的密码,然后,它密码返回给调用者。但是,其使用有限制:如果EnablePasswordReset为false,那么,Membership Provider就会抛出一个异常。如果RequiresQuestionAndAnswer是true,那么,必须使用它的具有一个参数的重载形式,传入密码答案才行。还好,我不需要RequiresQuestionAndAnswer,把EnablePasswordReset打开,也是小菜一碟。最后,在web.config中的Membership配置如下:<membership defaultProvider="QmxFavoriteMembershipProvider">
<providers>
<add connectionStringName="QmxFavoriteConnectionString"
applicationName="QmxFavorite"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="false"
requiresUniqueEmail="true"
passwordFormat="Hashed"
name="QmxFavoriteMembershipProvider"
type="System.Web.Security.SqlMembershipProvider"
minRequiredPasswordLength="6"
minRequiredNonalphanumericCharacters="0"/>
</providers>
</membership>
然后,在ASPX文件里放置一些用于重置密码的控件:
<providers>
<add connectionStringName="QmxFavoriteConnectionString"
applicationName="QmxFavorite"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="false"
requiresUniqueEmail="true"
passwordFormat="Hashed"
name="QmxFavoriteMembershipProvider"
type="System.Web.Security.SqlMembershipProvider"
minRequiredPasswordLength="6"
minRequiredNonalphanumericCharacters="0"/>
</providers>
</membership>
<div id="chgUserPwd">
<asp:Literal ID="ltlChgPwdTitle" runat="server" Text="修改用户密码"></asp:Literal><br />
用户名:<asp:Label ID="lblUserName" runat="server" /><br />
新密码:<asp:TextBox ID="tbPassword" runat="server" EnableViewState="False" /><br />
<asp:Literal runat="server" ID="ltlChgMessage" Text="" EnableViewState="false" /><br />
<asp:Button ID="btnSavePwd" runat="server" Text="修改" OnClick="btnSavePwd_Click" />
</div>
接下来,在BLL里把修改密码的代码写进去:
<asp:Literal ID="ltlChgPwdTitle" runat="server" Text="修改用户密码"></asp:Literal><br />
用户名:<asp:Label ID="lblUserName" runat="server" /><br />
新密码:<asp:TextBox ID="tbPassword" runat="server" EnableViewState="False" /><br />
<asp:Literal runat="server" ID="ltlChgMessage" Text="" EnableViewState="false" /><br />
<asp:Button ID="btnSavePwd" runat="server" Text="修改" OnClick="btnSavePwd_Click" />
</div>
public bool ChangeUserPassword(string userName, string txtPassword)
{
MembershipUser user = Membership.GetUser(userName);
try
{
string p=user.ResetPassword();
user.ChangePassword(p, txtPassword);
}
catch (Exception)
{
return false;
}
return true;
}
接下来,只要在按钮事件处理里调用此方法就可以了:
{
MembershipUser user = Membership.GetUser(userName);
try
{
string p=user.ResetPassword();
user.ChangePassword(p, txtPassword);
}
catch (Exception)
{
return false;
}
return true;
}
protected void btnSavePwd_Click(object sender, EventArgs e)
{
string userName = lblUserName.Text.Trim();
string password = tbPassword.Text;
if ((new FavUserIS()).ChangeUserPassword(userName, password))
{
ltlChgMessage.Text = "密码修改成功。";
}
else
{
ltlChgMessage.Text = "密码修改失败!";
}
}
这里,利用ResetPassword()方法返回新的密码的值,然后,再通过ChangePassword方法,来完成修改密码操作。这样做的缺点时,多了一次ResetPassword操作。脑袋不够用了,就先这么解决着吧。大家如果有更好的方法,一定留言告诉小弟。
{
string userName = lblUserName.Text.Trim();
string password = tbPassword.Text;
if ((new FavUserIS()).ChangeUserPassword(userName, password))
{
ltlChgMessage.Text = "密码修改成功。";
}
else
{
ltlChgMessage.Text = "密码修改失败!";
}
}
Little knowledge is dangerous.