2

사용자 지정 멤버 자격 공급자를 구현했으며이 공급자를 사용하는 웹 페이지에 암호 변경 컨트롤이 있습니다. 이 멤버 자격 공급자 클래스의 ChangePassword 메서드는 외부 웹 서비스에 연결하여 암호 강도 및 유효성에 대한 비즈니스 논리를 확인합니다. webservice는 새로운 암호가있는 경우 정확히 무엇이 잘못되었는지 (길이 문제, 특수 문자 필요 등) 정확하게 반환 할 수있는 기능이 있습니다.멤버 자격 공급자 ChangePassword 메서드 반환 형식 문제

이제, 사용자 지정 공급자에 의해 오버라이드 (override) 할 수있는과 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 컨트롤.

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

하는 방법을 사용자에게 올바른 비 정적/하드 비밀번호 변경 오류 메시지를 표시 할과 changepassword 컨트롤에 멤버 자격 공급자 클래스의과 changepassword 방법에서 특정 정보를 전송 다음은 ValidatingPassword 이벤트 핸들러의 코드는 ? ChangePassword 컨트롤에서 FailureInformation을 얻을 수 있도록 OnChangePassword 메서드에 대한 EventHandler의 ValidatePasswordEventArgs를 EventArgs에 연결하는 방법이 있습니까?

내 초기 연구에서 이것은 가능하지 않은 것처럼 보입니다. 비록 MS 팀이 이것을 간과하지 않았을 것이라고 생각하지만, 방법이 있어야합니다.

몇 포인터 :

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

+0

오, 내 눈! 이 제목은 불타고 있습니다! 조금 넣어주세요. –

+0

대단히 감사합니다! –

+0

나는 그것을 포기하지 않을 것이지만 데이터베이스 나 다른 것에 쓰는 것과 같은 해킹이 필요하다고 생각합니다. – Greg

답변

2

좋아요, 그래서 마침내 해결 방법을 찾았습니다. 그것은 가장 깨끗한 것은 아니지만, 내가 기본적으로 포함시켜야 할 곳에 가깝거나 가까운 곳에서 발견 할 수있는 유일한 사람입니다.

참고 : 데이터베이스 또는 쿠키에이 옵션을 유지할 수있는 옵션이 없습니다.

MembershipProviderChangePassword 메서드와 동일한 동작을 수행하지만 bool 대신 문자열을 반환하는 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"; 
} 

을 이제 ChangePassword 컨트롤의 onPasswordChanging 이벤트에 가입 :

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

나는 바이더로부터 정보를 전달하는 데 필요한 그냥 다른 쪽 끝을에 뽑힐하기 위해 부울을 반환하기 전에 쿠키를 설정 결국 한 번에 전화. 잘 했어.

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 메서드가 예외를 throw하는 것입니다. 예외에 오류 메시지가 있습니다!

관련 문제