Evil 域

当Evil遇上先知

导航

如何通过Membership编程修改他人密码?

Posted on 2007-05-12 00:00  Saar  阅读(2157)  评论(7编辑  收藏  举报
  在Membership编程的时候,通常会做到管理员给用户设置一个新密码的功能。然而,在MembershipProvider里,并没有提供相应的方法。
  MembershipUser类虽然提供了一个ChangePassword的方法,其原型如下:
public virtual bool ChangePassword (
    
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文件里放置一些用于重置密码的控件:
<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里把修改密码的代码写进去:
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;
}
接下来,只要在按钮事件处理里调用此方法就可以了:
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操作。脑袋不够用了,就先这么解决着吧。大家如果有更好的方法,一定留言告诉小弟。