2

我们已经实现了一个自定义成员资格提供者,对使用该供应商的网页更改密码控制。此成员资格提供程序类中的ChangePassword方法通过连接到外部Web服务来检查有关密码强度和有效性的一些业务逻辑。如果有新的密码(长度问题,需要特殊字符等),web服务有能力返回新密码的错误。现在成员资格提供ChangePassword方法返回类型问题

,是要通过自定义提供被覆盖的ChangePassword方法的签名是:

public override bool ChangePassword(string username, string oldPassword, string newPassword) 

所以即使我知道用新密码确切的问题的用户提供,我不能够将其显示在网页上,因为我只能从此方法返回true或false,并且更改密码控制会根据布尔返回值接管并执行自己的魔术。我可以挂钩的OnChangePasswordError事件ChangePassword控制的显示静态的错误信息,或者我甚至可以安装时出现此控制一些硬编码字符串的FailureText属性是一个错误,但我无法提供给用户什么他们提供的密码确实是错误的。

protected void OnPasswordChangeError(object sender, EventArgs e) 
     { 
      throw new MembershipPasswordException("Tell user what exactly is wrong with the password they supplied"); 
     } 

MembershipProvider类有一个ValidatingPassword事件之前,密码被更改时引发的,我可以通过检查密码是否符合标准,在这里抛出一个异常,但仍然是例外,似乎并没有传递到ChangePassword控件。下面是ValidatingPassword事件处理程序的代码:

void MyMembershipProvider_ValidatingPassword(object sender, ValidatePasswordEventArgs e) 
     { 
      //if password not valid 
      e.Cancel = true; 
      e.FailureInformation = new MembershipPasswordException(); 
      e.FailureInformation;   
     } 

如何从成员资格提供类ChangePassword控件的ChangePassword方法发送的特定信息,以显示正确的,非静态/硬编码口令更改错误消息给用户?有没有一种方法可以将ValidatePasswordEventArgs连接到EventHandler中的OnChangePassword方法的EventArgs,以便我可以在ChangePassword控件中获取FailureInformation?

从我最初研究这似乎并不可能。虽然我觉得MS团队不会忽略这一点,但应该有办法。

几个要点:

MembershipUser.ChangePassword fails without warning http://forums.asp.net/t/983613.aspx

+0

哦,我的眼睛!这个称号正在燃烧他们!请放一点儿。 – 2009-12-29 22:20:08

+0

非常感谢! – 2009-12-29 22:27:49

+0

我不会放弃它,但我认为你需要想出一个像写入数据库或其他东西的黑客。 – Greg 2010-01-29 22:01:48

回答

2

好了,我终于想通一个解决方法。它不是最干净的,但是我能找到的唯一一个,或者在任何地方发现的都接近默认应该包含的东西。

注:我没有在数据库或一个cookie保留此选项。

我创建具有相同的行为MembershipProviderChangePassword方法ChangePasswordNew方法,而是返回布尔值的字符串。所以,我的新的方法是这样的:

public string ChangePasswordNew(string username, string oldPassword, string newPassword) 
{ 
    //if password rules met, change password but do not return bool as MembershipProvider method does, 
    //return Success or the exact error for failure instead 
    if(passwordChangeRequirementsMet == true) 
    { 
     //change the password 
     return "success"; 
    } 
    else   
     return "exact reason why password cannot be changed"; 
} 

现在,订阅onPasswordChanging事件ChangePassword控制:

protected void PasswordIsChanging(object sender, LoginCancelEventArgs e) 
{ 
try 
    { 
     string response = Provider.ChangePasswordNew(username, currentPass, newPass); 
     if(response != "success") 
     { 
     changePwdCtrl.FailureText = response; 
     } 
    else 
    { 
    //cancel call to the default membership provider method that will attempt to 
    //change the password again. Instead, replicate the 'steps' of AttemptChangePassword(), 
    //an internal method of the ChangePassword control. 
    //Performing all the steps instead of calling the method because just calling method 
    //does not work for some reason 

    e.Cancel = true; 
    FormsAuthentication.SetAuthCookie(username, false); 
    OnPasswordChanged(sender, e); 

    MethodInfo successMethodInfo = changePwdCtrl.GetType().GetMethod("PerformSuccessAction",         BindingFlags.NonPublic | BindingFlags.Instance); 
    successMethodInfo.Invoke(changePwdCtrl, new object[] { "", "", changePwdCtrl.NewPassword }); 
} 
} 
catch(Exception ex) 
{ 
    LogException(ex); 
    throw; 
} 

} 

注:在这种情况下,如果密码错误变化,即回应不是“成功”,Memebership Provider ChangePassword方法仍然会被调用,并会再次返回一个错误。但是我已经将FailureText属性设置为在第一次调用中从响应返回的描述性错误,这是我的目标。在我的情况下,我不介意两个方法调用。你的情况可能会有所不同。

希望这可以帮助别人!

1

有一段时间,我需要传递信息了供应商和最终只设置一个cookie返回你的布尔之前在另一端被拾起的通话。工作很好。

2

你可以这样做,这样你就不会调用changepassword方法两次。

if(response != "success") 
     { 
     e.Cancel = true; 
((Literal)changePwdCtrl.ChangePasswordTemplateContainer.FindControl("FailureText")).Text = response; 
     } 

我创建处理这个自定义的MembershipProvider类,在会员类的ChangePassword方法抛出和特定消息的错误消息,我返回回控制字面更改密码控制的。

protected void ChangePassword1_ChangingPassword(object sender, LoginCancelEventArgs e) 
    { 
     try 
     { 
      ChangePassword c = (ChangePassword)sender; 

      MembershipUser mu = Membership.GetUser(c.UserName); 

      bool response; 

      try 
      { 
       response = mu.ChangePassword(c.CurrentPassword, c.NewPassword); 
      } 
      catch (Exception ex) 
      { 

       response = false; 
       e.Cancel = true; 
       //ChangePassword1.ChangePasswordFailureText = ex.Message; 
       //ChangePassword1_ChangePasswordError(sender, e);  
       //((Literal)ChangePassword1.ChangePasswordTemplateContainer.FindControl("FailureText")).Visible = true; 
       ((Literal)ChangePassword1.ChangePasswordTemplateContainer.FindControl("FailureText")).Text = ex.Message; 

      } 

      if (response) 
      {   
       //cancel call to the default membership provider method that will attempt to 
       //change the password again. Instead, replicate the 'steps' of AttemptChangePassword(), 
       //an internal method of the ChangePassword control. 
       //Performing all the steps instead of calling the method because just calling method 
       //does not work for some reason 

       e.Cancel = true; 
       FormsAuthentication.SetAuthCookie(c.UserName, false); 
       ChangePassword1_ChangedPassword(sender, e); 
       MethodInfo successMethodInfo = ChangePassword1.GetType().GetMethod("PerformSuccessAction", BindingFlags.NonPublic | BindingFlags.Instance); 
       successMethodInfo.Invoke(ChangePassword1, new object[] { "", "", ChangePassword1.NewPassword }); 

      } 
     } 
     catch (Exception ex) 
     {    
      throw; 
     } 
0

我相信一个更清洁的解决方法是ChangePassword方法引发异常。异常包含错误消息!

相关问题