2

カスタム メンバーシップ プロバイダーを実装し、このプロバイダーを使用する Web ページでパスワードの変更を制御します。このメンバーシップ プロバイダー クラスの ChangePassword メソッドは、外部 Web サービスに接続することにより、パスワードの強度と有効性に関するいくつかのビジネス ロジックをチェックします。Web サービスには、新しいパスワードに問題がある場合 (長さの問題、必要な特殊文字など) を正確に返す機能があります。

ここで、カスタム プロバイダーによってオーバーライドする必要がある ChangePassword メソッドのシグネチャは次のとおりです。

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

したがって、ユーザーが提供する新しいパスワードの正確な問題を知っていても、このメソッドから true または false しか返すことができず、パスワード変更コントロールが引き継いで独自の処理を行うため、Web ページに表示できません。ブール値の戻り値に応じたマジック。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 eventHandler のコードは次のとおりです。

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

メンバーシップ プロバイダー クラスの ChangePassword メソッドから ChangePassword コントロールに特定の情報を送信して、正しい非静的/ハードコーディングされたパスワード変更エラー メッセージをユーザーに表示する方法を教えてください。ChangePassword コントロールで FailureInformation を取得できるように、ValidatePasswordEventArgs を OnChangePassword メソッドの EventHandler の EventArgs に接続する方法はありますか?

私の最初の調査から、これは可能ではないようです。MSチームはこれを見逃さなかったと思いますが、方法があるはずです.

いくつかの指針:

MembershipUser.ChangePassword が警告なしで失敗する http://forums.asp.net/t/983613.aspx

4

4 に答える 4

2

代わりにこれを行うことができます。そうすれば、changepassword メソッドを 2 回呼び出すことはありません。

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

これを処理するカスタム メンバーシップ プロバイダー クラスを作成しました。メンバーシップ クラスの 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;
        } 
于 2010-10-24T04:34:54.527 に答える
2

わかりましたので、最終的に回避策を考え出しました。これは最もクリーンではありませんが、デフォルトで含まれているはずのものに近いものを思いついた、またはどこかで見つけた唯一のものです。

注: これをデータベースまたは Cookie に永続化するオプションがありませんでした。

ChangePasswordNewメソッドと同じ動作をするメソッドを作成しました MembershipProvider ChangePasswordが、bool ではなく string を返します。したがって、私の新しいメソッドは次のようになります。

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

次に、 Controlの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;
}

}

注:この場合、パスワードの変更でエラーが発生した場合、つまり応答が「成功」でない場合ChangePasswordでも、Memebership Provider メソッドが呼び出され、再度エラーが返されます。しかし、私はすでにFailureText最初の呼び出しで応答から返された記述的なエラーにプロパティを設定しています。これが私の目的でした。私の場合、2 つのメソッド呼び出しは気にしませんでした。あなたの場合は異なる場合があります。

これが誰かを助けることを願っています!

于 2010-02-22T23:00:49.170 に答える
1

ある時、私はプロバイダーから情報を渡す必要があり、コールの反対側でピックアップされるように bool を返す前に Cookie を設定するだけになりました。うまくいきました。

于 2010-02-17T23:29:32.307 に答える
0

よりクリーンな回避策は、ChangePassword メソッドが例外をスローすることだと思います。例外にはエラーメッセージが含まれています!

于 2016-12-16T03:21:45.813 に答える