1. 程式人生 > 實用技巧 >通過Nginx設定HttpOnly Secure SameSite引數解決Cookie跨域丟失

通過Nginx設定HttpOnly Secure SameSite引數解決Cookie跨域丟失

在前面的文章中“谷歌瀏覽器Chrome 80版本預設SameSite導致跨域請求Cookie丟失”,我們知道 Chrome 升級到80版本後,預設限制了跨域攜帶cookie給後端。我們也提到了可以修改Chrome的設定或在服務端新增SameSite設定來解決,但是普通的Web框架需要升級到最新版本才支援SameSite屬性,升級Web框架成本太高,因此本文使用Nginx來解決SameSite問題的辦法(需要使用Nginx反向代理站點)。

一、Cookie安全相關屬性

HttpOnly :

在Cookie中設定了“HttpOnly”屬性,通過程式(JS指令碼、Applet等)將無法讀取到Cookie資訊。

將HttpOnly 設定為true 防止程式獲取cookie後進行攻擊。

Secure :

安全性,指定Cookie是否只能通過https協議訪問,一般的Cookie使用HTTP協議既可訪問。

設定了Secure (沒有值),則只有當使用https協議連線時cookie才可以被頁面訪問。可用於防止資訊在傳遞的過程中被監聽捕獲後資訊洩漏。

SameSite:

Chrome瀏覽器在51版本後為 Cookie 新增的屬性,用來防止 CSRF 攻擊和使用者追蹤。可以設定三個值:Strict、 Lax、 None

Strict:完全禁止第三方 Cookie,跨站點時,任何情況下都不會發送 Cookie。換言之,只有當前網頁的 URL 與請求目標一致,才會帶上 Cookie。Set-Cookie: CookieName=CookieValue; SameSite=Strict;

Lax:規則稍稍放寬,大多數情況也是不傳送第三方 Cookie,但是導航到目標網址的 Get 請求除外。Set-Cookie: CookieName=CookieValue; SameSite=Lax;設定了Strict或Lax以後,基本就杜絕了 CSRF 攻擊。當然,前提是使用者瀏覽器支援 SameSite 屬性。

None:Chrome 計劃將Lax變為預設設定。這時,網站可以選擇顯式關閉SameSite屬性,將其設為None。不過,前提是必須同時設定Secure屬性(Cookie 只能通過 HTTPS 協議傳送),否則無效。Set-Cookie: key=value; SameSite=None; Secure

二、配置路徑

要通過nginx配置SameSite,可以在 nginx.conf 的 location 節點下進行配置:

proxy_cookie_path/"/;httponly;secure;SameSite=Lax";

配置示例:

server {
    listen 443 ssl http2;
    server_name www.demo.com;
    
    ssl_certificate /etc/letsencrypt/live/cat73.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/cat73.org/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/cat73.org/chain.pem;
    
    # add_header X-XSS-Protection "1; mode=block";
    # add_header X-Frame-Options SAMEORIGIN;
    add_header Strict-Transport-Security "max-age=15768000";
    
    location / {
        root /var/www/html;
    }
    
    location /api {
        proxy_pass http://localhost;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        # 配置位置如下
        proxy_cookie_path / "/; httponly; secure; SameSite=None";
    }
}