6

ASP.net アプリケーションでは、私が作成したカスタム メンバーシップ プロバイダーで Login コントロールを使用しています。私がやりたいことはThread.CurrentPrincipal、ユーザーが認証された直後に、カスタム プリンシパル オブジェクトに設定することです。

私はセッターを使用しています。Thread.CurrentPrincipalそれは私のためにプリンシパルオブジェクトを設定しますが、すべての後続スレッドで、この CurrentPrincipal はデフォルトのものでオーバーライドされます。

ログイン コントロールの Authenticate イベントのコードは次のとおりです。

protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
    {
        string username = Login1.UserName;
        string password = Login1.Password;

        if (Membership.ValidateUser(username, password))
        {
            var login = sender as Login;
            var phoenixIdentity = new PhoenixIdentity("B", "Forms" , true);
            var principal = new PhoenixPrincipal(phoenixIdentity);

            Thread.CurrentPrincipal = principal;
            AppDomain.CurrentDomain.SetThreadPrincipal(principal);

            HttpContext.Current.User = principal;

            e.Authenticated = true;
        }
    }

たとえば、ユーザー名 A でログインすると、すべてがうまくいくと想像してください... 検証はパスしますが、オブジェクトとして設定したプリンシパル オブジェクトに設定された Identity オブジェクトで、ユーザー名 B を使用してユーザーをハードコードしCurrentPrincipalます。

このメソッドの最後でどのユーザーがCurrentPrincipalID に設定されているかを確認すると、それはユーザー B であるCurrentPrincipalと表示されます。

CurrentPrincipalでは、オブジェクトを他のすべてのスレッドで永続化するにはどうすればよいですか? また、このログイン コントロールはいつどこでCurrentPrincipalスレッドのオブジェクトを設定するのでしょうか?

4

3 に答える 3

2

ただし、FormsAuthentication が正しく実装されていれば、この問題は発生しません。

ログインしなくてもページにアクセスできます。ログインページでのみ、スレッドの原則は手動で設定されますが、他の URL にアクセスすると、ログインページが呼び出されず、各ページが独自の異なるスレッドで実行されることを覚えています。最初のページをリクエストしてスレッドの原則を設定し、同じブラウザ インスタンスで 2 番目のページをリクエストした場合、まったく同じスレッドである場合とそうでない場合があります。

これが FormsAuthentication の仕組みです。

  1. Auth Cookie が設定されているかどうかを確認し、ユーザーをログイン ページに誘導します。
  2. ログインページは、FormsAuthentication.SetAuthCookie などの認証 Cookie を検証して設定する必要があります
  3. すべてのページ アクセスの前に、ステップ 1 が実行されます。
  4. Auth Cookie の検証が成功すると、ASP.NET はメンバーシップ コンポーネントに従って、現在のユーザーとすべてのさまざまなパラメーターを内部的に設定します。
  5. ASP.NET Global.asax ファイルでは、認証が成功した直後にチェックするコードをプラグインできるいくつかのイベントを提供できます。現在のユーザーを変更できます。ログイン ページで現在の原則を設定しても役に立たないことを覚えておいてください。

認証セッションが再構築されなかった後、特定の重要な情報を保存するためにセッションを使用していたときに同様の問題が発生したため、HTTP モジュールを作成し、その init メソッドで AfterRequestAcquired イベントを添付し、このイベントでインスタンス化するコードを記述できます。すべての重要なユーザー関連変数。

于 2009-08-31T08:58:56.460 に答える
1

これは私が FormsAuthentication_OnAuthenticate メソッドで行ったことです:

if (FormsAuthentication.CookiesSupported)
        {
            if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
            {
                try
                {
                    FormsAuthenticationTicket ticket = 
                        FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value);

                    var myIdentity = new GenericIdentity("B");
                    var principal = new GenericPrincipal(myIdentity, new string[]{"rola1"});
                    e.User = principal;
                }
                catch (Exception ex)
                {
                    // Decrypt method failed.
                }
            }
        }
        else
        {
            throw new HttpException("Cookieless Forms Authentication is not " +
                                    "supported for this application.");
        }

それがすべきことを機能しているようです...カスタムプリンシパル/アイデンティティペアをe.Userとして配置すると、次に修正する必要があるシリアル化の問題が発生します...ありがとうございます...

于 2009-08-31T10:04:00.820 に答える
1

FormsAuthentication_OnAuthenticate(object sender, FormsAuthenticationEventArgs e) (Global.asax 内) を処理し、ここで CurrentPrincipal を設定できます。


void FormsAuthentication_OnAuthenticate(object sender, FormsAuthenticationEventArgs e)
{
var phoenixIdentity = new PhoenixIdentity("B", "Forms" , true);
var principal = new PhoenixPrincipal(phoenixIdentity);
e.User = principal;
}
于 2009-08-31T08:45:26.207 に答える