通过删除 Set-Cookie 标头来利用 nginx 的代理缓存

通过删除 Set-Cookie 标头来利用 nginx 的代理缓存

以下是 Google Chrome 和 Apple Safari 使用的 WebKit 开发工具中的错误导致的结果。我做了一个使用 CrBug 报告错误,然后确定了回归WebKit 变更集 116952。我要感谢 @Grumpy 和 @Matthieu Cormier 帮助我追踪这个问题。我迫不及待地想要 Chrome Canary 的下一个版本 :)。


我的服务器上安装了 nginx 和 PHP-FPM,在创建新网站并尝试确保其尽可能快时,我使用了 Google Chrome 的审核工具。它给我的错误之一是这个。

Leverage proxy caching (10)
The following publicly cacheable resources contain a Set-Cookie
header. This security vulnerability can cause cookies to be shared
by multiple users.

所以我想知道的是,我必须在以下语句中添加什么才能使其不为该域设置 Set-Cookie 标头。然后我将获取该信息并将其应用于 css、img 等子域,以便浏览器可以正确缓存它。

server {
    gzip on;
    gzip_static on;

    listen          80;
    server_name     img.domain.tld;
    root            /www/domain/tld;
    index           index.php index.htm index.html;

    location ~* \.(gif|png|jpg|jpeg|svg)$ {
        expires 30d;
    }

    include php_fpm;
}

跟进请求提供更多信息脾气暴躁

这是我为 PHP FPM 包含的配置文件,用于 img 子域。

PHP-FPM包括

location ~ \.php$ {
    fastcgi_pass    unix:/tmp/php.socket;
    fastcgi_param   SCRIPT_FILENAME
                    $document_root$fastcgi_script_name;
    include         fastcgi_params;
}

如您所见,仅当位置以 php 文件扩展名结尾时才会激活。

有趣的是,我还有一个 css 文件,据报告该文件具有 set-cookie 标头,并且该文件由未包含 php-fpm 的 css 子域提供服务...这是配置文件的一部分。

server {
    gzip_static on;

    listen          80;
    server_name     css.domain.tld;
    root            /www/domain/css;
    index           index.htm index.html;

    location ~* \.(css)$ {
        expires 7d;
    }
}

这些文件是...

Leverage proxy caching (5)
    The following publicly cacheable resources contain a Set-Cookie 
    header. This security vulnerability can cause cookies to be shared
    by multiple users.
  • style.css(由样式表.域名.tld)
  • 2009EMSWeekLogoSmall.jpg(由 domain.tld 提供)
  • EMS%20FOUR.jpg(由 domain.tld 提供)
  • get_adobe_reader.png(由图片.域名.tld)
  • dhs-ntas-badge-small.jpg(由 dhs.gov 提供)

domain.tld 服务器配置如下所示。

server {
    gzip on;
    gzip_static on;

    listen          80;
    server_name     .domain.tld;
    root            /www/domain/www;
    index           index.php index.htm index.html;

    location ~* \.(htm|html|ico|icns|hqx|gif|png|svg|jpg|jpeg|svg)$ {
        expires 1d;
    }

    include php_fpm;
}

答案1

识别要缓存的资源是一种非默认行为。因此,无论是什么导致 Chrome 发出此通知,都是您指定要缓存的对象。

可以通过两种方式设置缓存指令(在本例中为公共)。

  1. 你的 nginx 告诉它进行缓存。
  2. PHP 告诉它缓存,然后由 nginx 转发。

根据上述 nginx 配置,并忽略整个include php_fpm;,除非您的图像(gif、jpg、png)以某种方式被执行,否则没有任何内容会建议#1。

PHP 也可能有这样的缓存指令。在这种情况下,您确实应该从核心开始修复,而不是尝试进行修补。

但是,在这两种情况下,你也可能遇到一种奇怪的情况。如果找不到你的图片,它会尝试查找 404 页面。如果 404 是可执行文件 (php),无论是直接还是间接,它都可以携带设置 cookie 命令。如果 404 指令还要求缓存,那么这将是一个糟糕的行为。所以,一定要检查这一点。这显然也适用于任何其他错误代码。

根据目前的信息,我只能猜测这些。您可能需要进一步了解导致 Chrome 发出此类消息的具体项目,以及是否发现任何错误以及 nginx 和/或 php-fpm 的完整配置。


我尝试查看完整的 HTTP 标头,看看是否有任何迹象表明有 cookie 或任何自定义信息被传递。

来自 OP 站点的示例响应标头导致警告。

telnet img.nassauems.net 80
Trying 205.186.162.66...
Connected to img.nassauems.net.
Escape character is '^]'.
GET http://img.nassauems.net/buttons/get_adobe_reader.png HTTP/1.1
Host: img.nassauems.net

HTTP/1.1 200 OK
Server: nginx/1.2.4
Date: Sat, 12 Jan 2013 20:24:19 GMT
Content-Type: image/png
Content-Length: 2597
Last-Modified: Fri, 28 Dec 2012 08:30:57 GMT
Connection: keep-alive
Expires: Mon, 11 Feb 2013 20:24:19 GMT
Cache-Control: max-age=2592000
Accept-Ranges: bytes

来自我的网站的示例响应标头不会引起警告。

telnet www.mysite.com 80
Trying 123.123.123.123...
Connected to www.mysite.com.
Escape character is '^]'.
GET http://www.mysite.com/test.png HTTP/1.1
Host: www.mysite.com

HTTP/1.1 200 OK
Server: nginx/1.0.12
Date: Sat, 12 Jan 2013 20:21:43 GMT
Content-Type: image/png
Content-Length: 207
Last-Modified: Sat, 27 Aug 2011 04:42:30 GMT
Connection: keep-alive
Expires: Sun, 13 Jan 2013 20:21:43 GMT
Cache-Control: max-age=86400
Accept-Ranges: bytes

你能发现差异吗?我找不到!

我会将其标记为 Chrome Audit 的一个错误。

答案2

虽然在您的情况下似乎您可能遇到了工具中的一些错误,该错误报告您的图形文件包含指令Set-Cookie(使用您描述的设置,您极不可能在由 nginx 直接提供的静态文件中拥有“Set-Cookie”内容),但我实际上遇到过这样一种情况,即 Java web 应用程序正在设置一些我不想设置的 cookie。

可以通过 nginx 解决这个问题,在上下文中放置以下指令server(根据需要更改proxy_fastcgi_

    proxy_hide_header       Set-Cookie;
    proxy_ignore_headers    Set-Cookie;
    # important! Remember the special inheritance rules for proxy_set_header:
    # http://nginx.org/ru/docs/http/ngx_http_proxy_module.html#proxy_set_header
    proxy_set_header        Cookie "";

上述三个指令都非常重要:proxy_hide_header确保标头不会传回客户端,proxy_ignore_headers确保标头不会自动禁用 nginx 中的缓存,最后proxy_set_header确保客户端无法将任何先前的 cookie 传递给 Web 应用程序并破坏缓存。请注意我关于继承的评论proxy_set_header— 您不能嵌套此指令(必须在给定级别定义全部或无)。

显然,您还必须确保在以上述方式删除 cookie 后,所有 webapps 仍能正常工作。但我亲身体验过,上述方法在删除 HTTP 传递的 cookie 方面确实非常有效!

答案3

我最近注意到了这一点,并且正在经历同样的事情。

我确信这是 Chrome 的一个错误。

  1. 我查看了 Safari Web Inspector 中的响应标头,它也没有显示 Set-Cookie。
  2. 我直接通过 telnet 连接到我的 Web 服务器并执行了 GET 请求,然后检查了原始标头,没有 Set-Cookie 行。

Chrome 可能正在检测某些东西并输出无效的描述,或者可能只是一个简单的错误。

在 OS X 上使用 Chrome 24.0.1312.52

在 OS X 上使用 Safari 版本 6.0.2 (8536.26.17)

相关内容