2

Мы внедрили пользовательский поставщик членства и сменили пароль на веб-странице, которая использует этот провайдер. Метод ChangePassword в этом классе поставщика членства проверяет некоторую бизнес-логику о силе и достоверности пароля, подключаясь к внешнему веб-сервису. Webservice имеет возможность возвращать точно, что не так с новым паролем, если он есть (проблемы с длительностью, специальный символ и т. Д.).Членство в поставщике ChangePassword Метод Тип возврата Задача

Теперь сигнатура метода ChangePassword, который должен быть переопределен с помощью настраиваемой провайдера:

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

Таким образом, даже если я знаю точную проблему с новым паролем поставки пользователь, я не могу чтобы отобразить его на веб-странице, потому что я могу только вернуть истину или ложь из этого метода, а управление паролем изменения затем берет на себя и выполняет свою собственную магию в зависимости от логического возвращаемого значения. Я могу подключить событие OnChangePasswordError элемента управления ChangePassword, чтобы показать статическое сообщение об ошибке, или я могу даже настроить свойство этого элемента управления на некоторую жестко закодированную строку при возникновении ошибки, но я не могу предоставить пользователю то, что точно не соответствует паролю, который они поставили.

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 EventHandler:

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

как послать определенную информацию из метода ChangePassword класса поставщика членства к контролю ChangePassword для отображения правильного, не являющееся статического/жёстко пароль сообщения об ошибках изменения к пользователю ? Есть ли способ подключить ValidatePasswordEventArgs к EventArgs в EventHandler для метода OnChangePassword, чтобы я мог получить информацию об ошибке в элементе управления ChangePassword?

Из моего первоначального исследования это не представляется возможным. Хотя я чувствую, что команда MS не упустила бы это из виду, и должен быть способ.

Несколько указателей:

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

+0

О, мои глаза! Этот заголовок горит! Пожалуйста, положите немного. –

+0

Спасибо большое! –

+0

Я бы не отказался от этого, но я думаю, вам нужно придумать взломать, как записать его в базу данных или что-то в этом роде. – Greg

ответ

2

ОК, поэтому я, наконец, решил обходное решение. Это не самое чистое, но единственное, что я мог придумать или найти где-нибудь, что было близко к тому, что должно было быть включено по умолчанию.

Примечание: У меня не было возможности сохранить это в базе данных или в файле cookie.

Я создал метод ChangePasswordNew, который имеет то же поведение, что и метод MembershipProviderChangePassword, но возвращает строку вместо bool.Так что мой новый метод будет выглядеть следующим образом:

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

В свое время мне нужно было передать информацию из поставщика, вылившиеся просто установив печенье до возвращения вашего BOOL, чтобы забрать на другом конце вызова. Отлично.

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 для исключения исключений. Исключение содержит сообщение об ошибке!