5月27日 21:45

什么是 SameSite Cookie?它如何防御 CSRF 和 XSS 攻击?

答案

SameSite 是 Cookie 的一个属性,控制浏览器是否在跨站请求中携带 Cookie。它是防御 CSRF 攻击的核心手段,也能在一定程度上限制跨站 XSS 的危害扩散。

三种模式的区别:

模式跨站请求是否携带 Cookie典型场景
Strict完全不携带银行、支付等高安全应用
Lax仅顶层导航(如点击链接)携带,异步请求不携带大多数 Web 应用的推荐默认值
None全部携带,必须配合 Secure第三方登录、iframe 嵌入等跨站场景
javascript
res.cookie('sessionId', token, { httpOnly: true, secure: true, sameSite: 'lax' // 现代浏览器默认值 });

为什么 Lax 是推荐默认值?

Strict 最安全但有体验问题:用户从邮件或搜索引擎点击链接进入网站时,Cookie 不会被发送,导致登录态丢失。Lax 在安全与体验间取了平衡——顶层 GET 导航携带 Cookie 保证正常跳转,POST 和异步请求不携带,阻断 CSRF。

SameSite 能防 XSS 吗?

不能完全防。SameSite 限制的是跨站请求中的 Cookie 发送,但 XSS 发生在同站内,脚本可以直接读取非 HttpOnly 的 Cookie 或发起同站请求。正确做法是 SameSite + HttpOnly + CSP 组合使用:

javascript
res.cookie('sessionId', token, { httpOnly: true, secure: true, sameSite: 'strict' }); // 配合 CSP 限制脚本来源 res.setHeader('Content-Security-Policy', "script-src 'self'");

None 模式有什么坑?

SameSite=None 必须同时设置 Secure,否则浏览器会拒绝。而且 None 模式下 Cookie 在所有跨站请求中都会发送,等于放弃了 SameSite 的防护,必须额外依赖 CSRF Token 等机制兜底。

追问

  • Chrome 80+ 未显式设置 SameSite 时默认行为是什么?——默认 Lax,未声明的 Cookie 在跨站 POST/iframe/fetch 中不会发送。
  • SameSite=Lax 下,哪些跨站请求会携带 Cookie?——顶层 GET 导航(<a> 点击、window.open),不包含 POST 表单、iframe、fetch/XHR。
  • 如果应用需要嵌入第三方 iframe 并保持登录态,怎么处理?——SameSite=None; Secure + CSRF Token 双重防护。
标签:XSS