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

这是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条缓存线有什么作用?

欢呼:)

此代码的存在允许您将[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的特定实例)并保存在静态缓存中,因此所有inheritanceAuthorizeAttribute的类型必须是线程安全的。

对AuthorizeCore的调用将validation请求是否已获得授权。 如果获得授权,它会放置一个AddValidationCallback,以便根据缓存策略测试缓存的输出是否仍然有效。 如果是,则将缓存的输出发送到客户端。

关于缓存的3行; 首先,您应该了解输出缓存必须正确或尽可能正确。 为了确保其“正确性”,系统将测试它是否满足某些条件(例如,它没有被修改)。 这可以在3行中完成。