ChangePassword Provider Membership Return Method Type Problem

We have implemented a user membership provider and changed the password on the web page that uses this provider. The ChangePassword method in this class of the membership provider checks some business logic about the strength and validity of the password by connecting to an external web service. Webservice has the ability to return exactly what is wrong with the new password, if there is one (problems with duration, special character, etc.).

Now the signature of the ChangePassword method, which must be canceled by the customer, is as follows:

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

Thus, although I know the exact problem with the new password that the user provides, I can’t display it on the web page, because I can only return true or false from this method, and then changes the password and takes care of it own magic depending on the logical return value. I can OnChangePasswordError on the ChangePassword control's OnChangePasswordError event to show a static error message, or I can even set the FailureText property of this control to some string with a hard code when an error occurs, but I cannot provide the user with something that does not exactly match the password, which they provided.

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

The MembershipProvider class has a ValidatingPassword event that is raised before the password is changed, and here I can throw an exception by checking if the password meets the criteria, but still this exception does not seem to be passed to the ChangePassword control. Here is the code for the ValidationPassword eventHandler:

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

how to send specific information from the ChangePassword method of the membership provider class to the ChangePassword control to display the correct error messages to the user, not static / hard-coded with errors? Is there a way to connect ValidatePasswordEventArgs to EventArgs in EventHandler for the OnChangePassword method so that I can get error information in the ChangePassword control?

From my initial research this is not possible. Although I feel that the MS team would not lose sight of this, and there must be a way.

A few pointers:

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

+2
asp.net-membership membership-provider asp.net-webcontrol
source share
4 answers

Ok, so I finally decided a workaround. This is not the cleanest, but the only one I could find or find somewhere that was close to what should have been enabled by default.

Note. I have not been able to save this in a database or in a cookie.

I created the ChangePasswordNew method, which has the same behavior as the MembershipProvider ChangePassword method, but returns a string instead of bool. So my new method would look like this:

 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"; } 

Now subscribe to the onPasswordChanging ChangePassword Control event:

 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; } } 

Note: In this case, if there is an error when changing the password, that is, the answer is not a β€œsuccess”, the Memebership Provider ChangePassword method will still be called and will return an error, But I already set the FailureText property FailureText descriptive error received from the answer in the first call that was my goal. I did not mind the two method calls in my case. Your case may be different.

Hope this helps someone!

+2
source share

You can do this instead, so you do not call the changepassword method twice.

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

I created my own membershipprovider class that handles this, the changepassword method in the membership class message and the error message of the specific message, and I return it back to the change password control's control literal.

 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; } 
+2
source share

At one time, I needed to transfer information from the provider and in the end I just set a cookie before returning your bool, which will be selected at the other end of the call. It works great.

+1
source share

I believe the exception is a more complicated solution for the ChangePassword method. The exception contains an error message!

0
source share

All Articles