【问题标题】:Using a Header to Filter Proxied Response Headers使用标头过滤代理响应标头
【发布时间】:2019-05-14 05:16:16
【问题描述】:

我有一个上游服务器,它经常通过返回“Set-Cookie”响应标头来设置 Cookie。

我想在上述上游服务器前面有一个 nginx 代理:

Browser => Nginx => Upstream

如果Browser => Nginx 请求具有标头X-No-Cookies: true,我希望Upstream => Nginx => Browser 的响应不包含Set-Cookie 响应标头。如果X-No-Cookies 有任何其他值,我会撒谎Set-Cookie 响应标头以原样返回。 我无法更改上游服务器的响应标头行为。

目前我的nginx配置如下,具体注意proxy_hide_header指令的使用。我还在X-No-Cookies 响应标头中回显了$proxy_hide_header 变量。

map $http_x_no_cookies $proxy_hide_header {
  default "";
  "true"  "Set-Cookie";
}

# Homepage
server {
  listen 80;
  server_name example.com;

  location /api {
    proxy_pass        https://example.com/api;
    proxy_hide_header $proxy_hide_header;
    add_header        "X-No-Cookies" $proxy_hide_header;
  }
}

当我使用 cURL 发出请求时:

curl \
  http://example.com/api \
  -H 'X-No-Cookies: true' \
  -I

我得到以下响应标头:

Server: nginx/1.12.2
Date: Thu, 13 Dec 2018 02:26:41 GMT
Content-Type: application/json
Content-Length: 2255
Connection: keep-alive
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Accept,Authorization
Access-Control-Allow-Methods: GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS
Access-Control-Expose-Headers: Content-Length
Set-Cookie: foo=bar; Max-Age=2592000; Expires=Sat, 12 Jan 2019 02:26:41 GMT; Path=/; Domain=example.com; Secure
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-No-Cookies: Set-Cookie

每当proxy_hide_header 提供一个 nginx 变量作为参数时,它似乎都没有效果。如果我将变量替换为字符串($proxy_hide_header 替换为 "Set-Cookie"),我会得到所需的行为 - Set-Cookie 响应标头被省略。

编辑:我已将此问题的代码推送到 GitHub

  • 我原来的(非工作)实现是here
  • Ivan Shatsky 的解决方案是here

【问题讨论】:

    标签: http nginx nginx-reverse-proxy


    【解决方案1】:

    多么有趣的挑战啊!确实,$proxy_hide_header 不接受变量作为其参数,并且不能在 if 块内使用。此外,我们不能直接在 location 块内使用 $upstream_... 变量,因为它的值尚未评估。最后我找到了解决方案。我们总是隐藏Set-Cookie 标头,然后在需要时重新设置,通过map 表达式计算值:

    map $http_x_no_cookies $hide_cookies {
        default "0";
        "true"  "1";
    }
    
    map $hide_cookies$upstream_http_set_cookie $cookies {
        ~^0(.*)$ $1;
    }
    
    upstream backend {
        server example.com;
    }
    
    server {
        listen 80;
        server_name example.com;
    
        location /api {
            proxy_pass        https://backend/api;
            proxy_hide_header Set-Cookie;
            add_header Set-Cookie $cookies;
        }
    }
    

    【讨论】:

    • 你怎么知道 proxy_hide_header 不接受变量作为它的参数?我正在阅读此文档 (nginx.org/en/docs/http/…),但找不到该信息。
    • 我认为这可以称为经验 :) 除非某些指令的 nginx 文档明确指出可以将变量用作其参数,否则通常意味着它们不能。这是 nginx 记录指令的方式。
    • @Ivan 你认为有多个 cookie 的解决方案吗?此解决方案仅适用于一个 cookie。我在这里工作:stackoverflow.com/questions/46470330/…
    • @Vixxs 使用标头很棘手,我想如果我遇到这样的问题,我会尝试使用 OpenResty 解决它。它是一个带有嵌入式 Lua 脚本的 nginx 分支。查看this 问题以查看一些示例。
    • @Ivan 嗨,我在同一个 Nginx 安装中使用了一点 Lua,我是这方面的新手,你能检查我的解决方案吗,你认为它可靠吗?:stackoverflow.com/questions/46470330/…
    猜你喜欢
    • 2012-03-30
    • 2021-08-29
    • 2014-10-10
    • 2016-05-06
    • 2012-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-05
    相关资源
    最近更新 更多