18

新しいasp.net mvc 4.0アプリケーションを作成するとき、最初に行うことglobal filterの1つは、次のようにカスタム承認を作成して設定することです。

//FilterConfig.cs
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
 //filters.Add(new HandleErrorAttribute());
 filters.Add(new CustomAuthorizationAttribute());
}

次に、次のCustomAuthorizationAttributeように作成します。

//CustomAuthorizationAttribute.cs
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAjaxRequest())  
        {
            //Handle AJAX requests
            filterContext.HttpContext.Response.StatusCode = 403;
            filterContext.Result = new JsonResult { JsonRequestBehavior = JsonRequestBehavior.AllowGet };
        }
        else
        {
            //Handle regular requests
            base.HandleUnauthorizedRequest(filterContext); //let FormsAuthentication make the redirect based on the loginUrl defined in the web.config (if any)
        }
    }

私は2つのコントローラーを持っています:HomeControllerそしてSecureController

HomeController は[AllowAnonymous]属性で装飾されています。

SecureController は属性で装飾されていません。[AllowAnonymous]

Index() ActionResultHomeController、単純なボタンを含むビューを表示します。

SecureControllerボタンをクリックすると、次のような内部に存在する GetData() メソッドへの ajax 呼び出しを行います。

$("#btnButton").click(function () {
    $.ajax({
        url: '@Url.Action("GetData", "Secure")',
        type: 'get',
        data: {param: "test"},
        success: function (data, textStatus, xhr) {
            console.log("SUCCESS GET");
        }
    });
});

言うまでもなく、ボタンをクリックすると、グローバル フィルターであるだけでなく、 が属性で装飾されていないCustomAuthorizationAttributeため、 がトリガーされます。SecureController[AllowAnonymous]

よし、自己紹介終わった…

の導入により、認証フィルターの前にたまたまトリガーasp.net mvc 5.0される新しい機能が導入されました(これは優れており、認証されていないユーザー (http 401) と認証されていないユーザーを区別する方法をより細かく制御できます)。認証されていて、たまたま承認されていない人 (http 403))。authentication filter

この新しいauthentication filter機能を試すために、新しい asp.net mvc 5.0 (VS Express 2013 for Web) を作成し、次のことから始めました。

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    //filters.Add(new HandleErrorAttribute());
    filters.Add(new CustomAuthenticationAttribute());   //Notice I'm using the word Authentication and not Authorization
}

次に、属性:

public class CustomAuthenticationAttribute : ActionFilterAttribute, IAuthenticationFilter 
{
    public void OnAuthentication(AuthenticationContext filterContext)
    {

    }

    public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
    {
        var user = filterContext.HttpContext.User;
        if (user == null || !user.Identity.IsAuthenticated)
        {
            filterContext.Result = new HttpUnauthorizedResult();
        }
    }
}

を作成しましたHomeController。は属性HomeControllerで装飾されています。[AllowAnonymous]

VS 2013 からアプリケーションを起動する前に、CustomAuthenticationAttribute (OnAuthenticationおよびOnAuthenticationChallenge) の両方のメソッド内に 2 つのブレーク ポイントを設定しました。

アプリケーションを起動すると、最初のブレーク ポイント ( OnAuthentication) にヒットします。次に、驚いたことに、 内のコードIndex() ActionResultHomeController 実行され、View() を返した後でのみ、メソッドのブレーク ポイントに到達しOnAuthenticationChallenge()ます。

質問: 2 つの質問があります。

質問 1)属性は自動的にコードをバイパス
するという印象を受けましたが、それは間違いでした! 属性の存在を手動で確認し、コードをスキップする必要がありますか?[AllowAnonymous]CustomAuthenticationAttribute[AllowAnonymous]

Index()質問 2) myの my メソッド内のコードが のHomeController実行されるのはなぜですか? View() を返した後、内部のコードが実行されることに気付くだけですか?OnAuthenticationOnAuthenticationChallenge()

Index()私の懸念は、ユーザーが認証されていない場合にメソッドのコードを実行したくないということです。

おそらく、私はこれを間違った方法で見ています。

誰かがこれに光を当てるのを手伝ってくれるなら、それは素晴らしいことです!

敬具ヴィンス

4

3 に答える 3

8

質問 1 への回答:

[AllowAnnoymous] 属性はフラグのように機能します (実際には実装ロジックは含まれていません)。その存在は、OnAuthorization の実行中に [Authorize] 属性によってチェックされるだけです。[Authorize] 属性を逆コンパイルすると、ロジックが明らかになります。

        bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true)
                                 || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true);

        if (skipAuthorization)
        {
            return;
        }

[AllowAnnonymous] は、カスタム属性のコードを「自動的に」バイパスすることはありません...

したがって、質問 1 の後半の答えは次のとおりです。はい - カスタム属性を [AllowAnnonymous] の存在に反応させたい場合は、[AllowAnnonymous] のチェック (上記と同様) を実装する必要があります。カスタム [Authorize] 属性の属性。

于 2014-04-21T14:51:13.747 に答える
6

に関して: 質問 1) [AllowAnonymous] 属性が CustomAuthenticationAttribute 内のコードを自動的にバイパスするという印象を受けましたが、間違っていました! [AllowAnonymous] 属性の存在を手動で確認し、コードをスキップする必要がありますか?

私の知る限り、[AllowAnonymous] 属性は CustomAuthenticationAttribute とは何の関係もありません。それらにはさまざまな目的があります。[AllowAnonymous] は、承認コンテキストでは効果がありますが、認証コンテキストでは効果がありません。

認証コンテキストを設定するために認証フィルターが実装されました。たとえば、AuthenticationContext は、認証を実行するための情報を提供します。この情報を使用して、現在のコンテキストに基づいて認証を決定できます。たとえば、認証コンテキストに基づいて ActionResult を別の結果タイプに変更することを決定したり、認証コンテキストなどに基づいて現在のプリンシパルを変更することを決定したりする場合があります。

OnAuthenticationChallenge メソッドは、OnAuthentication メソッドの後に実行されます。OnAuthenticationChallenge メソッドを使用して、リクエストに対して追加のタスクを実行できます。

に関して: 質問 2) HomeController の Index() メソッド内のコードが OnAuthentication の後に実行されるのはなぜですか? View() を返した後、 OnAuthenticationChallenge() 内のコードが実行されることに気付くだけですか?

これは予期される動作です。グローバルに登録された認証フィルターがあるため、最初に、アクションが実行される前に、お気づきのように OnAuthentication イベントが発生します。次に、インデックスが実行された後の OnAuthenticationChallenge。アクションが成功すると、そのアクション (つまり、インデックス) に関連する認証フィルターは、OnAuthenticationChallenge を実行して、アクションの結果に貢献できるようにします。OnAuthenticationChallenge のコードにあるように、ActionResult を HttpUnauthorizedResult に変更できます。これは ActionResult とネゴシエートされます。

于 2013-10-25T12:46:03.460 に答える
5

ここで、2 番目の質問を明確にする必要があります。

質問 2) HomeController の Index() メソッド内のコードが OnAuthentication の後に実行されるのはなぜですか? View() を返した後、 OnAuthenticationChallenge() 内のコードが実行されることに気付くだけですか?

ユーザーがアクション メソッドでコードを実行できないようにする場合は、実際に OnAuthentication で資格情報をテストする必要があります。OnAuthenticationChallenge は、ユーザーをカスタム コントローラー/アクションにリダイレクトして認証の機会を与えるなど、カスタム結果で 401 を処理するチャンスです。

public class CustomAuthenticationAttribute : ActionFilterAttribute, IAuthenticationFilter 
{
    public void OnAuthentication(AuthenticationContext filterContext)
    {
            var user = filterContext.HttpContext.User;
        if (user == null || !user.Identity.IsAuthenticated)
        {
            filterContext.Result = new HttpUnauthorizedResult();
        }
    }

    public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
    {
        // modify filterContext.Result to go somewhere special...if you do
        // nothing here they will just go to the site's default login
    }
}

フィルターのより完全な実行とその操作方法は次のとおりです

乾杯。

于 2013-11-19T19:53:25.270 に答える