【问题标题】:Can someone explain this block of ASP.NET MVC code to me, please?有人可以向我解释这段 ASP.NET MVC 代码吗?
【发布时间】:2011-02-28 07:24:21
【问题描述】:

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

干杯:)

【问题讨论】:

  • 好吧,我猜它正在为 .. 上下文设置一些缓存 .. 这意味着响应。但是,那个年龄是..现在?而且我不知道这个回调是什么/做什么/如何或何时触发。

标签: c# asp.net-mvc caching authorization authorize-attribute


【解决方案1】:

此代码允许您将 [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 子类必须是线程安全的。

【讨论】:

  • Reflector 来了解这一点。为什么?当我使用自己的自定义 AuthorizeAttribute 时,缓存不起作用。 (代码位于 codeplex MVCContrib fork - 可插入 REST 框架中),因为每个请求都在调用 这三行。正如你所说,输出缓存模块检测到匹配,它将重新运行 AC 方法 ..这是我的问题 :( No cookies == no authentication remembers, 所以我需要对每个 Request 进行身份验证。 . 并且缓存被重置?例如:bit.ly/bJcntB
  • /我希望他能打电话给你 Levi @ MS 聊天 :)
【解决方案2】:

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

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

【讨论】:

  • 您能解释一下第二行的作用和原因吗?接下来,您能否解释一下 AddValidationCallback 的作用/是/为什么等。您所说的就是……如果一个人添加了 [Authorize] 属性,则调用此代码。但是,如果一个人还添加了一个 [OutputCache] 属性,那么上面的 3 行就会产生效果。如果是这样 - 如何?请参考一些 MVC 代码作为解释证明。
  • cache.SetProxyMaxAge(new TimeSpan(0L)) 是无缓存的更好选择;它会导致缓存重新验证,但它不会阻止缓存。另一方面,No-cache 将导致根本不缓存任何内容。
  • 所以你说第二行停止缓存输出,如果有一些OutputCache。他们为什么要这样做?
  • 它不会阻止输出被缓存,但它会导致缓存条目被重新验证。
猜你喜欢
  • 2011-08-20
  • 1970-01-01
  • 2011-05-31
  • 1970-01-01
  • 2022-12-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多