c# - 有人可以向我解释这段 ASP.NET MVC 代码吗?

标签 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();
    }
}

因此,如果我被“授权”,则执行一些缓存操作,否则抛出 401 Unauthorized 响应。

问题:这 3 条缓存线是做什么的?

干杯:)

最佳答案

此代码的存在允许您将 [OutputCache] 和 [Authorize] 放在一起进行操作,而不会冒为授权用户生成的响应被缓存并提供给未授权用户的风险。

这是来自 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.

那么这个属性到底在做什么呢?它首先禁用此响应的代理缓存,因为代理无法正确确定哪些用户有权或无权查看它。如果代理向未经授权的用户提供响应,那将是一件非常糟糕的事情。

现在 AddValidationCallback 怎么样?在 ASP.NET 中,输出缓存模块 Hook 在 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 管道照常运行以生成响应。

顺便说一句,由于委托(delegate)是针对 AuthorizeCore 形成的(从而捕获 AuthorizeAttribute 的特定实例)并保存在静态缓存中,这就是为什么所有子类化 AuthorizeAttribute 的类型都必须是线程安全的。

关于c# - 有人可以向我解释这段 ASP.NET MVC 代码吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2983030/

相关文章:

c# - 带有正则表达式的 JToken.SelectToken 用于查找与模式匹配的值?

C# Socket.receive 连续接收0字节,循环不阻塞

c# - 在 ASP.NET MVC 中设置 CheckBox 的 Checked 属性

asp.net - HttpRuntime.Cache 不适合网络农场?

iphone - iPhoneOS 会自动清除库/缓存吗?

angularjs - Angular 和 Spring 服务器缓存 .js 和 .html 文件

c# - 如何获取实现 IMyInterface 的引用中的所有类型

c# - 如何增加原始音频字节的音量/振幅

c# - EF6 存储过程必须声明标量变量

javascript - 为什么我的 TextBoxFor 不能正确显示货币值?