使用nginx,如何有条件地隐藏来自后端的多个set-cookie响应头?

时间:2016-04-08 20:09:20

标签: nginx

我使用fastcgi_pass进行了nginx配置。我确定它与proxy_pass一样有效。

对于匿名/访客用户,我希望隐藏由php set-cookie设置的session_start()响应标头(我也隐藏了cache-controlexpirespragma标头),但对于已登录的用户(以及匿名用户登录时),我希望传递后端发送的所有set-cookie标头。

我让应用程序设置了一个特殊的标题(X-SPECIAL)我可以在nginx中检查它以决定它是什么类型的响应 - 对于客人与否。

当后端发送单个set-cookie标头时,我仅在需要时使用$upstream_http_set_cookie成功传递它。但是当后端使用多个set-cookie响应头设置多个cookie时,$upstream_http_set_cookie只包含一个值,因此客户端只能看到一个cookie。这导致登录无法正常工作。

如何获取$upstream_http_set_cookie中的所有值? 或者,如何有条件地设置fastcgi_hide_headers?我知道hide_headers不支持变量,似乎不能按请求设置不同。

我是否必须使用openresty和lua?

我的配置:

fastcgi_cache_path /var/nginx/cache levels=1:2 keys_zone=my_cache:10m;

map $upstream_http_x_special $not_store_in_cache {
  default "1";
  guest "0";
}

map $upstream_http_x_special $maybe_set_cookie {
  default $upstream_http_set_cookie;
  guest "";
}

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /usr/share/nginx/html;
    index index.php index.html index.htm;

    server_name localhost;

    location / {
        try_files $uri $uri/ =404;
    }

    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }

    location ~ \.php$ {
        try_files $uri =404;

        set $not_from_cache "";
        if ($request_method !~ ^(GET|HEAD)$) {
            set $not_from_cache "1";
        }
        if ($cookie_phpsessid != '') {
            set $not_from_cache "1";
        }
        # conditionally don't serve request from cache
        fastcgi_cache_bypass $not_from_cache;
        # conditionally don't store response into cache
        fastcgi_no_cache $not_from_cache$not_store_in_cache;
        fastcgi_cache my_cache;
        fastcgi_cache_key $scheme$host$request_uri;
        fastcgi_cache_valid any 1s;
        # serve from cache while generating next response
        fastcgi_cache_use_stale error timeout updating http_500 http_503;
        # single request to backend, no matter how many requests for same resource.
        fastcgi_cache_lock on;
        # store in cache regardless of response headers
        fastcgi_ignore_headers expires cache-control set-cookie;
        # remove these headers from response before passing back to client.
        fastcgi_hide_header pragma;
        fastcgi_hide_header expires;
        fastcgi_hide_header cache-control;
        fastcgi_hide_header x-special;

        # Fake conditional hide response header by always hiding and
        # conditionally adding it back.
        # Works only when there is a single "set-cookie" header,
        # fails when backend sets multiple cookies.
        fastcgi_hide_header set-cookie;
        add_header Set-Cookie $maybe_set_cookie;

        # standard code for php backend
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

1 个答案:

答案 0 :(得分:0)

这是设置$not_from_cache以避免问题if的方法。不是一个完整的答案,但可能会导致一个更多的帮助:

map $request_method,$cookie_phpsessid,$uri $not_from_cache {
    default 0;
    ~*^POST,[^,]*,.*\.php$ 1; # match php POST request
    ~*,[^,]+,.*\.php$ 1;      # match php request with $cookie_phpsessid set
}