有人可以向我解释这个ASP.NET MVC代码块吗?

Pur*_*ome 5 c# asp.net-mvc caching authorization authorize-attribute

这是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();
    }
}
Run Code Online (Sandbox Code Playgroud)

所以,如果我'授权'然后做一些缓存的东西,否则抛出401 Unauthorized响应.

问题:这3条缓存线有什么作用?

欢呼:)

Lev*_*evi 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;
}
Run Code Online (Sandbox Code Playgroud)

这实际上只是将AuthorizeCore方法与缓存的响应相关联.当输出缓存模块检测到匹配时,它将重新运行AuthorizeCore方法以确保允许当前用户真正看到缓存的响应.如果AuthorizeCore返回true,则将其视为缓存命中(HttpValidationStatus.Valid),并且响应从缓存提供,而不通过MVC管道.如果AuthorizeCore返回false,则将其视为缓存未命中(HttpValidationStatus.IgnoreThisRequest),并且MVC管道像往常一样运行以生成响应.

顺便说一下,由于委托形成了AuthorizeCore(因此捕获AuthorizeAttribute的特定实例)并保存在静态缓存中,因此所有类型的子类化AuthorizeAttribute都必须是线程安全的.