介紹
跨站請求(Cross-Site Request)通常是指瀏覽器在訪問一個網站時,向另一個域名的網站發送請求的行為。這個概念在 Web 安全中非常重要,尤其是在涉及到“跨站請求偽造(CSRF)”和“跨域資源共享(CORS)”時。
? 原理:
-
用戶登錄了網站 A(比如網銀),獲得了身份 Cookie;
-
惡意網站 B 引導用戶訪問一個看不見的表單或圖片鏈接;
-
瀏覽器默認會自動攜帶 Cookie 發起請求;
-
網站 A 接收到請求,并以為是用戶主動發起的操作;
-
被攻擊了!
<img src="https://bank.com/transfer?to=badguy&amount=1000" />
CORS 設置(針對跨域資源共享)
? 服務器通過 Access-Control-Allow-Origin 控制哪些域可以訪問資源
? 默認禁止 JavaScript 跨域請求敏感信息
CSRF 防御:
? 使用 CSRF Token(后端生成一個隱藏字段或 header,必須攜帶)
? 使用 SameSite 屬性限制 Cookie 跨站發送
? 檢查 Referer 來源
? POST 請求驗證身份
同源限制
?A 網站不能直接訪問 B 網站的 Cookie。
這是瀏覽器的**同源策略(Same-Origin Policy)**保護的。
? 什么是 Cookie 同源限制?
同源 = 協議 + 域名 + 端口 都相同
瀏覽器規定:
一個網站(origin)設置的 Cookie,只能被這個網站自己訪問。
🔒 比如:
網站 | 可訪問的 Cookie 域 |
---|---|
https://a.com | 只能訪問屬于 a.com 的 Cookie |
https://b.com | 不能訪問 a.com 的 Cookie |
所以,即使你設置了“允許所有 Cookie”,瀏覽器還是會自動隔離不同網站之間的 Cookie。
🍪 那些“Allow all cookies”是啥意思?
這些是用戶給瀏覽器設置的權限,意思是:
? 是否允許 第三方 Cookie(Third-Party Cookies)。
? 比如:你在 a.com 上訪問,但頁面里加載了 b.com 的 iframe / 圖片 / script,這些操作是否可以讓瀏覽器存取 b.com 的 Cookie。
<!-- 你在訪問 a.com -->
<iframe src="https://b.com/login"></iframe>
如果瀏覽器允許第三方 Cookie,b.com 的頁面可以設置 Cookie,這個 Cookie 是屬于 b.com 的。
?? 你在 a.com 的 JS 代碼還是訪問不到?b.com 的 Cookie!
強限制SameSite
🔒 SameSite 是啥?
SameSite 是瀏覽器用來限制 Cookie 在跨站請求中是否可以攜帶的一個 Cookie 屬性。
是 Cookie 本身帶的設置,告訴瀏覽器:“這個 Cookie 什么時候可以被發送?”
📋 SameSite 的三種取值:
值 | 含義 | 跨站請求是否帶 Cookie? | 場景 |
---|---|---|---|
Strict | 嚴格模式 | ?完全禁止 | 安全性最高,比如網銀登錄 |
Lax | 寬松模式 | ?允許 GET 導航(如點擊鏈接) | 登錄頁面跳轉 |
None | 無限制 | ?允許所有跨站請求,但需要加 Secure(HTTPS) | 跨站 API、第三方登錄等 |
假設你在 a.com 登錄后有個 Cookie:sessionid=abc123,設置了:
# Django/FastAPI 設置 Cookie 的時候加:
response.set_cookie(key="sessionid",value="abc123",samesite="strict",secure=True,
)
如果你后來從 b.com 發起一個請求到 a.com:
// 你在 b.com 上寫了
fetch('https://a.com/api/userinfo', { credentials: 'include' })
🔒 瀏覽器不會攜帶 sessionid=abc123,因為你設置了 SameSite=Strict。
? 原因:
? 防止 CSRF 攻擊(跨站請求偽造)
? 增加賬戶安全性
? 默認更“保守”,開發者自己決定放開(改為 Lax 或 None)
?注意:
? 如果你的網站需要 跨站點請求+登錄狀態,比如前端 a.com、后端 api.a.com,就不能用 Strict,你要用:
SameSite=None; Secure
如果后端不使用 Cookie,而是使用 Authorization Header(比如 JWT)做身份驗證,那 SameSite=Strict 對你來說根本不重要,完全沒影響。
🔐 傳統 Cookie 登錄(狀態保存在服務器):
? 登錄成功后后端設置 cookie:
Set-Cookie: sessionid=abc123; SameSite=Strict
? 每次請求,瀏覽器自動帶上 cookie:
Cookie: sessionid=abc123
這時候 SameSite=Strict 會阻止瀏覽器在跨站請求中攜帶這個 Cookie,比如別人惡意發起跨站 POST 請求,防止 CSRF。
項目類型 | 使用 Cookie 嗎? | 是否需要關注 SameSite? |
---|---|---|
傳統后端渲染(Django 模板) | ? 是 | ? 需要,最好設為 Lax 或 Strict |
前后端分離 + Cookie 登錄 | ? 是 | ? 必須關注(建議 None + Secure) |
前后端分離 + JWT 登錄 | ? 否 | ? 不用管 SameSite,隨它去 |
Https_only
https_only=True(也叫 secure=True)確實是為了強制瀏覽器只在 HTTPS 請求時發送 Cookie,而且它的確跟你的測試環境用 HTTP 有沖突。
在 Django / FastAPI / Flask 里,如果你設置:
response.set_cookie(key="sessionid",value="abc123",secure=True # 或 https_only=True
)
它的作用是:
🚫 瀏覽器只會在
HTTPS 請求
? 如果是 HTTP 請求,瀏覽器會完全忽略這個 Cookie。
🔐 為什么要這么做?
? 防止中間人攻擊(Man-in-the-middle attack)
? 保證 Cookie 不被 HTTP 劫持或監聽
? 是現代 Web 安全的基本要求,特別是在登錄、權限等敏感操作中非常重要