5

これは、ASP.NET MVC2 (RTM)System.Web.Mvc.AuthorizeAttributeクラスの現在のコードです:-

public virtual void OnAuthorization(AuthorizationContext filterContext)
{
    if (filterContext == null)
    {
        throw new ArgumentNullException("filterContext");
    }
    if (this.AuthorizeCore(filterContext.HttpContext))
    {
        HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
        cache.SetProxyMaxAge(new TimeSpan(0L));
        cache.AddValidationCallback(
            new HttpCacheValidateHandler(this.CacheValidateHandler), null);
    }
    else
    {
        filterContext.Result = new HttpUnauthorizedResult();
    }
}

したがって、「承認済み」の場合はキャッシュを行い、そうでない場合は 401 Unauthorized 応答をスローします。

質問:これら 3 つのキャッシング ラインは何をしますか?

乾杯 :)

4

2 に答える 2

15

このコードは、許可されたユーザーに対して生成された応答がキャッシュされ、許可されていないユーザーに提供されるというリスクを冒すことなく、アクションに [OutputCache] と [Authorize] の両方を配置できるようにするために存在します。

AuthorizeAttribute.cs のソース コード コメントは次のとおりです。

アクション レベルで承認を実行しているため、承認コードは出力キャッシュ モジュールの後に実行されます。最悪の場合、これにより許可されたユーザーがページをキャッシュすることが可能になり、後で許可されていないユーザーにキャッシュされたページが提供される可能性があります。プロキシに機密性の高いページをキャッシュしないように指示することでこれを回避し、カスタム認証コードをキャッシュ メカニズムにフックして、キャッシュからページを提供するかどうかの最終決定権を持っています。

では、この属性は何をしているのでしょうか? プロキシは、どのユーザーが表示を許可されているか、または許可されていないかを適切に判断できないため、最初にこの応答のプロキシ キャッシュを無効にします。また、プロキシが無許可のユーザーに応答を提供する場合、これは非常に悪いことです。

AddValidationCallback はどうでしょうか。ASP.NET では、出力キャッシュ モジュールが、HTTP ハンドラーのに実行されるイベントをフックします。MVC は実際には単なる特別な HTTP ハンドラーであるため、出力キャッシュ モジュールがこの応答が既にキャッシュされていることを検出した場合、モジュールは MVC パイプラインをまったく経由せずにキャッシュから直接応答を提供することを意味します。出力キャッシュが無許可のユーザーに応答を提供する場合、これは潜在的に非常に悪いことでもあります。

CacheValidateHandlerを詳しく見てみましょう。

private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus) {
    validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
}

// This method must be thread-safe since it is called by the caching module.
protected virtual HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext) {
    if (httpContext == null) {
        throw new ArgumentNullException("httpContext");
    }

    bool isAuthorized = AuthorizeCore(httpContext);
    return (isAuthorized) ? HttpValidationStatus.Valid : HttpValidationStatus.IgnoreThisRequest;
}

これは事実上、AuthorizeCoreメソッドをキャッシュされた応答に関連付けるだけです。出力キャッシュ モジュールが一致を検出すると、AuthorizeCore メソッドを再実行して、現在のユーザーがキャッシュされた応答を実際に表示できることを確認します。AuthorizeCore が true を返した場合、キャッシュ ヒット (HttpValidationStatus.Valid) として扱われ、応答は MVC パイプラインを経由せずにキャッシュから提供されます。AuthorizeCore が false を返す場合、キャッシュ ミス (HttpValidationStatus.IgnoreThisRequest) として扱われ、MVC パイプラインが通常どおり実行されて応答が生成されます。

余談ですが、デリゲートは AuthorizeCore に対して形成され (したがって、AuthorizeAttribute の特定のインスタンスをキャプチャします)、静的キャッシュに保存されるため、AuthorizeAttribute をサブクラス化するすべての型はスレッドセーフでなければなりません。

于 2010-06-07T01:23:03.683 に答える
2

AuthorizeCore への呼び出しは、リクエストが承認されているかどうかを検証します。承認された場合、キャッシュされた出力がキャッシュ ポリシーに従ってまだ有効かどうかをテストするために、AddValidationCallback を配置します。その場合、キャッシュされた出力がクライアントに送信されます。

キャッシュ用の3行について; まず最初に、出力キャッシュが正確であるか、可能な限り正確でなければならないことを理解する必要があります。その「正しさ」を測定するために、システムは特定の条件 (たとえば、変更されていない) を満たしているかどうかをテストします。これは、3行で実行できるものです..

于 2010-06-06T04:40:46.003 に答える