Varnish - 分离和附加 cookie

Varnish - 分离和附加 cookie

首先,我想了解一下这是否可能。

因此,我可以看到,如果 Varnish 有 cookie,它就不会缓存对象。

我在想,当传入的请求带有 cookie 时,Varnish 会将它们存储在变量中并删除这些 cookie,然后将其传递到后端。一旦后端完成处理,Varnish 就会将 cookie 放回原处。

这是可能的吗?

如果是,那么 vcl 是什么样子的?

答案1

语境

Varnish 在缓存方面比较保守,并且认为使用 cookie 意味着响应的个性化程度。

缓存个性化响应可能会导致隐私或安全问题。它还可能导致输出不一致。

想象一下缓存一个包含购物车的页面。缓存整个页面将导致每个人都拥有相同的购物车价值。

以下是 Varnish 对 cookie 的内置 VCL 行为:

  • 当 VarnishCookie在请求中看到标头时,它不会从缓存中提供对象,因为它假定内容是个人化的。

https://www.varnish-software.com/developers/tutorials/varnish-builtin-vcl/#authorization-headers-and-cookies-are-not-cacheable

  • 当 VarnishSet-Cookie在响应中看到标头时,它不会将对象存储在缓存中,因为设置 cookie 是一种状态改变,也意味着个性化。

https://www.varnish-software.com/developers/tutorials/varnish-builtin-vcl/#dont-cache-responses-with-set-cookie-headers

剥饼干

一旦通过响应标头设置了 cookie Set-Cookie,它将作为请求标头传递Cookie给每个后续请求,即使对于那些实际上不需要这些 cookie 的页面也是如此。

这就是为什么确定哪些页面需要 Cookie 以及哪些页面不需要 Cookie 很重要。识别跟踪 Cookie 也同样重要,因为它们是由客户端在 Javascript 中处理的,而不是在服务器上处理的。

下面是一个 VCL 示例,其中我们删除了所有 cookie,只留下服务器上需要的 cookie:

vcl 4.1;

sub vcl_recv {
    if (req.http.Cookie) {
        set req.http.Cookie = ";" + req.http.Cookie;
        set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
        set req.http.Cookie = regsuball(req.http.Cookie, ";(PHPSESSID)=", "; \1=");
        set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
        set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");
    }
    if (req.http.cookie ~ "^\s*$") {
        unset req.http.cookie;
    }
}

在这种情况下,只PHPSESSID保留 cookie,因为需要跟踪登录。如果在替换逻辑之后此 cookie 仍然存在,Varnish 将不会从缓存中提供响应。如果未设置此 cookie,但存在一堆跟踪 cookie,则所有 cookie 都将被删除,并且可以从缓存中提供页面。

删除特定页面的 Cookie

尽管前面的示例去除了选定的 cookie 并仅保留了PHPSESSIDcookie,但您最终仍可能会访问实际上不需要该会话 cookie 的页面。

下面是一个 VCL 示例,其中 cookie 被完全剥离,但实际上需要特定 cookie 的页面除外,例如管理页面和购物车页面:

vcl 4.1;

sub vcl_recv {
    if(req.url ~ "^/admin" || req.url == "/cart") {
        return(pass);
    }
    unset req.http.Cookie;
}

删除 Set-Cookie 标头

如图所示https://www.varnish-software.com/developers/tutorials/varnish-builtin-vcl/#dont-cache-responses-with-set-cookie-headersSet-Cookie,如果使用标头,内置 VCL 将不会将对象存储在缓存中,因为它意味着状态改变。

但是,这并不意味着该页面永远不会进入缓存:下一个后端响应可能不包含标Set-Cookie头,因为 cookie 已设置。在这种情况下,没有Set-Cookie标头的下一个响应可能会进入缓存。

然而,如果您确定不需要为某些页面设置 cookie,那么您也可以决定删除标题Set-Cookie

以下示例阻止后端为静态内容设置 cookie:

vcl 4.1;

sub vcl_backend_response {
    if (bereq.url ~ "^[^?]*\.(7z|avi|bmp|bz2|css|csv|doc|docx|eot|flac|flv|gif|gz|ico|jpeg|jpg|js|less|mka|mkv|mov|mp3|mp4|mpeg|mpg|odt|ogg|ogm|opus|otf|pdf|png|ppt|pptx|rar|rtf|svg|svgz|swf|tar|tbz|tgz|ttf|txt|txz|wav|webm|webp|woff|woff2|xls|xlsx|xml|xz|zip)(\?.*)?$") {
        unset beresp.http.Set-Cookie;
    }
}

重新附加 cookies

虽然可以将 cookie 值存储在标头中,然后剥离 VCL 中的 cookie 以从缓存中提供服务,最后重新附加到后端请求,但这实际上并没有多大意义。

如果可缓存响应不需要 cookie 来创建其输出,为什么要为后端请求发送 cookie?

如果后端请求需要 cookie 值来组成输出,则可能意味着响应将无法缓存,因此您不妨完全绕过该请求的缓存。

下一步

因为你的问题不是很具体,所以我也必须给你一个非常笼统的回答。

如果我的回答完全回答了您的问题,我邀请您详细说明您的用例,作为回报,我会给您更详细的答复。

相关内容