![Varnish - 分離和附加cookie](https://rvso.com/image/782600/Varnish%20-%20%E5%88%86%E9%9B%A2%E5%92%8C%E9%99%84%E5%8A%A0cookie.png)
首先,我想知道這是否可能。
所以,我可以看到如果 Varnish 有 cookie,它就不會快取物件。
我正在考慮當傳入請求有 cookie 時,Varnish 會將它們儲存在變數中並刪除這些 cookie,然後讓它通過後端。一旦後端處理完成,Varnish 就會放回 cookie。
這是可能的嗎?
如果是的話,vcl 是什麼樣子的?
答案1
情境
Varnish 在快取方面是保守的,並假設 cookie 的使用意味著回應的個人化程度。
快取個人化回應可能會導致隱私或安全問題。它也可能導致輸出不一致。
想像一下快取一個包含購物車的頁面。快取整個頁面將導致每個人都具有相同的購物車價值。
以下是 Varnish 對 cookie 的內建 VCL 行為:
- 當 Varnish 看到
Cookie
請求中的標頭時,它不會從快取中提供對象,因為它假設內容是個人化的。
- 當 Varnish
Set-Cookie
在回應中看到標頭時,它不會將物件儲存在快取中,因為設定 cookie 是一種狀態更改,也意味著個人化。
剝離餅乾
一旦透過回應標頭設定了 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 並僅保留PHPSESSID
cookie,但您仍然可能會看到實際上不需要該會話 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-headers,如果使用標頭,內建 VCL 不會將物件儲存在快取中Set-Cookie
,因為這表示狀態變更。
然而,這並不意味著該頁面永遠不會在快取中結束:下一個後端回應可能不會包含標頭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;
}
}
重新附加 cookie
雖然可以將 cookie 值儲存在標頭中,然後在 VCL 中剝離 cookie 以從快取中提供服務,最後重新附加後端請求,但這並沒有多大意義。
如果可緩存回應不需要 cookie 來建立其輸出,為什麼要為後端請求發送 cookie?
如果後端請求需要 cookie 值來組成輸出,則可能表示回應將不可緩存,因此您最好完全繞過該請求的快取。
下一步
因為你的問題不是很具體,所以我也不得不給你一個非常籠統的答案。
如果我的回答完全回答了您的問題,我邀請您指定有關您的用例的更多詳細信息,作為回報,我將為您提供更詳細的答复。