IIS / ASP.NET使用缓存控制进行响应:对所有请求都是私有的

时间:2017-11-10 14:06:01

标签: asp.net asp.net-mvc caching iis

为什么ASP.NET的所有响应都包含Cache-Control: private?即使是404响应? IIS中是否有设置此默认值的东西,有没有办法配置它?或者ASP.NET中有什么设置这个?

对于动态内容(即所有MVC结果),我不希望它被浏览器缓存,因为它是动态的,可以随时更改。静态内容托管在CDN上,因此IIS不提供。

编辑:

为了澄清,我非常了解Cache-Control: private是什么,privatepublicno-store等之间的区别以及如何/何时使用它们。我的问题是IIS / ASP.NET默认添加Cache-Control: private的原因以及默认情况下如何防止它被添加。我知道可以对缓存动态页面很有用,但在我的应用程序中,我 想要缓存动态页面/响应。例如,我不希望缓存XHR JSON响应,因为它们包含动态内容。不幸的是,服务器会自动为所有响应添加Cache-Control: private,因此我必须在任何地方手动覆盖它。

如何重现:打开visual studio并使用MVC创建一个新的ASP.NET框架(是的,框架,不是Core。我们无法将我们的系统迁移到核心)解决方案项目。现在在IIS Express中启动项目(只需按下播放按钮),然后在浏览器中使用F12 devtools查看http响应。您会看到它包含Cache-Control: private。我的问题是,添加此标题的内容是什么,以及如何防止在默认情况下添加

enter image description here

6 个答案:

答案 0 :(得分:5)

将我的位置添加到上面的答案中;

<强> 1。 http缓存标题attrubute Cache-Control:IIS / ASP.NET默认添加了private?

缓存请求指令

标准Cache-Control指令,客户端可以在HTTP请求中使用它。

    Cache-Control: max-age=<seconds>
    Cache-Control: max-stale[=<seconds>]
    Cache-Control: min-fresh=<seconds>
    Cache-Control: no-cache 
    Cache-Control: no-store
    Cache-Control: no-transform
    Cache-Control: only-if-cached

缓存响应指令

标准Cache-Control指令,服务器可以在HTTP响应中使用。

    Cache-Control: must-revalidate
    Cache-Control: no-cache
    Cache-Control: no-store
    Cache-Control: no-transform
    Cache-Control: public
    Cache-Control: private
    Cache-Control: proxy-revalidate
    Cache-Control: max-age=<seconds>
    Cache-Control: s-maxage=<seconds>

IIS使用安全且更明显/有用的默认设置,这恰好是私有的

<强> 2。如何防止默认添加?

IIS / asp.net允许从引入之日起配置它,如thisref1ref2ref3ref4

System.Web Namespace

  

System.Web命名空间提供了启用浏览器 - 服务器通信的类和接口。此命名空间包括System.Web.HttpRequest类,该类提供有关当前HTTP请求的大量信息; System.Web.HttpResponse类,它管理客户端的HTTP输出;和System.Web.HttpServerUtility类,它提供对服务器端实用程序和进程的访问。 System.Web还包括用于cookie操作,文件传输,异常信息和输出缓存控制的类。

protected void Application_BeginRequest()
{
  Context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
}

答案 1 :(得分:3)

来自RickNZ

https://forums.asp.net答案

Cache-Control private表示客户端可以根据其到期日期缓存页面。到期时间可以使用Cache-Control:max-age或Expires HTTP标头提供。在默认情况下,页面设置为立即过期,这意味着它不会被缓存。

Cache-Control的目的之一:private实际上是告诉中间代理他们不应该缓存页面。

BTW,仅仅因为页面是动态的并不意味着它永远不应该被缓存。在许多情况下,缓存动态页面是合适的。您不仅可以在客户端缓存,还可以在代理和服务器的输出缓存中缓存。

更多信息:

IIS 7.0 - IIS adding "private" to cache-control, where is that coming from

Private vs Public in Cache-Control

https://msdn.microsoft.com/en-us/library/ms524721(v=vs.90).aspx

https://msdn.microsoft.com/en-us/library/system.web.httpcacheability(VS.71).aspx

https://forums.asp.net/t/1443346.aspx?Cache+control+private+

https://forums.asp.net/t/2052325.aspx?Remove+the+private+value+from+the+Cache+Control+in+the+Response+Header

答案 2 :(得分:2)

TL; DR

  1. 默认情况下,动态ASP.NET页面不使用缓存。您需要努力在ASP.NET中启用缓存。
  2. “Cache-Control:private”标题的存在并不意味着页面的缓存版本将用于重复请求。
  3. -

    验证上述陈述的测试非常简单。创建一个返回当前时间的操作:

    public ActionResult Index()
    {
        ViewBag.CurrTime = DateTime.Now.ToString("T");
        return View();
    }
    

    查看:

    @{
        ViewBag.Title = "Home Page";
    }
    
    <h1>@ViewBag.CurrTime</h1>
    

    如果你在abrowser中刷新这样的页面,你会在每个请求上看到新的时间:

    enter image description here

    enter image description here

    有可能在ASP.NET MVC中使用缓存,但您应该努力启用它。有关详细信息,请参阅此article

    如果尽管如此,您仍然出于某种原因想要排除任何缓存的可能性,您可以通过设置特定的HTTP标头来实现。有一个很棒的SO answer列出了应该设置的标题:

    Cache-Control: no-cache, no-store, must-revalidate
    Pragma: no-cache
    Expires: 0
    

    您可以使用操作过滤器在每个ASP.NET响应中设置这些标头:

    public class CachingHeadersFilterAttribute : ActionFilterAttribute
    {
        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            var response = filterContext.HttpContext.Response;
    
            response.Cache.SetCacheability(HttpCacheability.NoCache);
            response.Cache.AppendCacheExtension("no-store, must-revalidate");
            response.AppendHeader("Pragma", "no-cache");
            response.AppendHeader("Expires", "0");
    
            base.OnResultExecuted(filterContext);
        }
    }
    

    在FilterConfig.cs中(在ASP.NET MVC模板中自动创建):

    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            filters.Add(new CachingHeadersFilterAttribute());
        }
    }
    

    以下是回复中的结果标题:

    HTTP/1.1 200 OK
    Cache-Control: no-cache, no-store, must-revalidate
    Pragma: no-cache
    Content-Type: text/html; charset=utf-8
    Expires: -1
    Vary: Accept-Encoding
    Server: Microsoft-IIS/10.0
    X-AspNetMvc-Version: 5.2
    X-AspNet-Version: 4.0.30319
    X-SourceFiles: =?UTF-8?B?RDpcRHJvcGJveFxwcm9nXFN0YWNrT3ZlcmZsb3dcUTQ3MjI0NTYxQ2FjaGVcUTQ3MjI0NTYxQ2FjaGU=?=
    X-Powered-By: ASP.NET
    Date: Mon, 13 Nov 2017 17:44:33 GMT
    Content-Length: 837
    

    如您所见,没有'Cache-Control:private'标题。

    但是,我再也没有看到为什么要在应用程序中添加此类过滤器的原因。

答案 3 :(得分:2)

  

是什么添加了此标题?

IIS 7及更高版本(包含在默认安装中)将其作为缓存相关的HTTP标头之一发送给Web客户端。

  

如何防止默认情况下添加它?

我描述了两种基于您的问题禁用缓存机制(服务器端方法和客户端方法)的方法,重点放在服务器端:

服务器端方法

按照以下步骤在 Internet信息服务(IIS)管理器内更改Cache-Control值(,而我认为这适用于静态内容):

  1. 连接窗格中,转到站点应用程序,或者 目录,您要禁用缓存
  2. 主页窗格中,双击 HTTP Response Headers
  3. 点击操作窗格中的 Set Common Headers ....
  4. 选中复选框 expire Web content ,选择在特定时间间隔或特定时间后过期的选项, 然后单击“确定”。
  5. 一种方法是按如下方式注释您的控制器,它非常强大,响应头包含Cache-Control: publicmax-age=0标题。:

    [OutputCache(Duration = 0)]
    public class SomeController : Controller  {
    
    }
    

    您还可以在应用程序的 Web.config 文件中定义缓存配置文件,并在配置文件中包含durationvaryByParam设置:

    <caching>
      <outputCacheSettings>
        <outputCacheProfiles>
          <add name="nocache" duration="0" 
            varyByParam="none" />
        </outputCacheProfiles>
      </outputCacheSettings>
    </caching>
    

    然后在动作/控制器之前使用[OutputCache CacheProfile="nocache"]

    请注意 web.config 文件(以下)中有一个配置不会阻止缓存。相反,它只是表明不应该应用任何类型的缓存机制。通过禁用输出缓存,我们得到ASP.net MVC使用的默认缓存头,它回落到Cache-Control: private,从而再次打开浏览器缓存请求的可能性。

    <caching>
        <outputCache enableOutputCache="false" />
    </caching>
    

    客户端方法

    在js请求中使用cache: false,例如:

    $.ajax({
        type: 'GET',
        cache: false,
        url: '/nation',
        ...
    });
    

    如需其他信息,请访问:

答案 4 :(得分:1)

解决问题:

  

您将看到它包含Cache-Control:private。我的问题是,   添加此标题的内容,以及如何防止添加此标题   默认?

简短回答是:正如其他人所说,这是IIS(7 +)的默认设置。

更全面地回答:如果您希望控制或修改默认设置Cache-Control: private以缓存HTTP请求,服务器端。

这取决于您运行的IIS的特定版本,以及您希望修改的具体方式。一般来说,您可以使用 HTTP响应标头界面(在 IIS管理器 =&gt; 功能视图 - IIS)中执行此操作

如果您只想禁用网站或应用程序的缓存:

  1. 转到 IIS管理器
  2. 选择所需的网站/应用
  3. 功能视图中的
  4. 选择 HTTP响应标头
  5. 在操作窗格中,点击:设置常用标题
  6. 检查过期网页内容
  7. 设置为:立即
  8. 或者,从您的命令行:

    appcmd.exe set config  "Default Web Site" -section:system.webServer/staticContent /clientCache.cacheControlMode:"DisableCache" 
    

    有关详细信息和具体信息,请查看:

    https://docs.microsoft.com/en-us/iis/configuration/system.webserver/staticcontent/clientcache

    希望这是你所寻找的,欢呼。

答案 5 :(得分:1)

默认在 System.Web.HttpResponse.CacheControl 中指定:

        /// <devdoc>
        ///    <para>
        ///       Provided for ASP compatiblility. Use the <see cref='System.Web.HttpResponse.Cache'/>
        ///       property instead.
        ///    </para>
        /// </devdoc>
        public string CacheControl {
            get {
                if (_cacheControl == null) {
                    // the default
                    return "private";
                }

                return _cacheControl;
            }

虽然您可以通过(全局)过滤器覆盖标头,但这不适用于由身份验证/授权引起的错误页面。幸运的是,每个请求都有一个很好的入口点,允许您覆盖此默认值:

// In Global.asax.cs:
        protected void Application_BeginRequest()
        {
            Context.Response.CacheControl = "no-cache";
        }

此外,当出现错误并且通过 ReportRuntimeError 呈现 YSOD(黄色错误页面)时,框架将调用 ClearHeaders,并且您的自定义缓存控制设置将被覆盖。我还没有找到解决方案。