Can someone explain this block of ASP.NET MVC code to me, please?

前端 未结 2 1911
傲寒
傲寒 2021-01-01 02:52

this is the current code in ASP.NET MVC2 (RTM) System.Web.Mvc.AuthorizeAttribute class :-

public virtual void OnAuthorization(AuthorizationConte         


        
2条回答
  •  隐瞒了意图╮
    2021-01-01 03:23

    This code exists to allow you to put both [OutputCache] and [Authorize] together on an action without running the risk of having a response that was generated for an authorized user cached and served to a user that is not authorized.

    Here's the source code comment from AuthorizeAttribute.cs:

    Since we're performing authorization at the action level, the authorization code runs after the output caching module. In the worst case this could allow an authorized user to cause the page to be cached, then an unauthorized user would later be served the cached page. We work around this by telling proxies not to cache the sensitive page, then we hook our custom authorization code into the caching mechanism so that we have the final say on whether a page should be served from the cache.

    So just what is this attribute doing? It first disables proxy caching of this response, as proxies can't make the proper determination of which users are or are not authorized to view it. And if a proxy serves the response to an unauthorized user, this is a Very Bad Thing.

    Now what about AddValidationCallback? In ASP.NET, the output caching module hooks events that run before the HTTP handler. Since MVC is really just a special HTTP handler, this means that if the output caching module detects that this response has already been cached, the module will just serve the response directly from cache without going through the MVC pipeline at all. This is also potentially a Very Bad Thing if the output cache serves the response to an unauthorized user.

    Now take a closer look at 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;
    }
    

    This effectively just associates the AuthorizeCore method with the cached response. When the output cache module detects a match, it will re-run the AuthorizeCore method to make sure that the current user really is allowed to see the cached response. If AuthorizeCore returns true, it's treated as a cache hit (HttpValidationStatus.Valid), and the response is served from cache without going through the MVC pipeline. If AuthorizeCore returns false, it's treated as a cache miss (HttpValidationStatus.IgnoreThisRequest), and the MVC pipeline runs as usual to generate the response.

    As an aside, since a delegate is formed to AuthorizeCore (thus capturing the particular instance of AuthorizeAttribute) and saved in a static cache, this is why all types subclassing AuthorizeAttribute must be thread-safe.

提交回复
热议问题