cookie的SameSite属性

SameSite 是 Cookie 的一种属性,主要用于防止跨站请求伪伪造(CSRF,Cross-Site Request Forgery)攻击。它通过控制第三方 Cookie 的发送时机,来保护用户的隐私和安全。

在深入 SameSite 之前,我们需要明确两个概念:

  • 第一方 Cookie (First-party Cookie): 你当前访问的网站(地址栏里的域名)写入的 Cookie。
  • 第三方 Cookie (Third-party Cookie): 页面中嵌入的其他网站(如广告、图片、iframe 插件)写入的 Cookie。

1. 核心概念:什么是"同站 (Same-Site)"?

SameSite 的"站(Site)"和我们平时说的"同源策略 (Same-Origin)"不同,它的定义更宽松。

满足以下条件的两个 URL 被认为是同站(Same-Site)的:

有效顶级域名 + 一级域名(eTLD+1) 相同

  • TLD 是指 .com.org 等。
  • eTLD(有效顶级域名)是指像 .com.cn.co.uk 这种复合域名。
  • 举个例子:
    • www.baidu.comtieba.baidu.com 属于同站 (因为都是 baidu.com)。
    • baidu.comgoogle.com 属于跨站(Cross-Site)
    • a.github.iob.github.io 属于跨站 (因为 github.io 是一个 eTLD,它的下一级才是一级域名)。

2. SameSite 的三种策略值

SameSite 属性可以设置三个值:StrictLaxNone

① SameSite=Strict (严格模式)

这是最安全的模式。

  • 规则: 任何跨站的请求(无论通过什么方式触发)都绝不发送该 Cookie。只有当你在当前域名下操作,或者地址栏域名完全一致时才会携带。
  • 场景: 比如你在百度(baidu.com)页面里点击了一个指向淘宝(taobao.com)的链接。即使你之前在淘宝登录过,由于是跨站跳转,浏览器在请求淘宝时不会 带上淘宝的 Strict Cookie。
  • 优缺点: 防御 CSRF 效果最好,但极度影响用户体验(比如从邮件里点开一个知乎链接,进去了却发现需要重新登录)。

② SameSite=Lax (宽松模式)

这是目前主流浏览器的默认模式(平衡了安全与体验)。

  • 规则: 拒绝大部分跨站 Cookie 的发送,但允许"导航到目标网址的常规安全跳转"携带 Cookie。
  • 具体而言,只有满足以下两个条件时,跨站请求才会带上 Lax Cookie:
    1. HTTP 方法必须是安全的(通常是 GETPOSTPUTDELETE 等绝对不带。
    2. 必须是顶级导航(Top-level navigation),即该请求会导致浏览器地址栏的 URL 发生变化。
  • 允许带 Lax Cookie 的场景:
    • <a href="..."> 链接跳转。
    • <link rel="prerender" href="..."> 预加载。
    • window.location.replace("...") 或表格的 GET 提交。
  • 禁止带 Lax Cookie 的场景:
    • ajax / fetch 请求。
    • <img src="..."><iframe src="..."><script src="..."> 等隐式加载的资源。
    • POST 表单提交。

③ SameSite=None (无限制)

关闭 SameSite 限制。

  • 规则: 无论同站还是跨站,任何请求都会带上 Cookie(回到了当年的传统行为)。
  • 硬性前提条件: 现代浏览器(Chromium 80 及以上)规定,如果设置了 SameSite=None,就必须同时设置 Secure 属性 。这意味着该 Cookie 只能通过 HTTPS 协议传输,否则浏览器会直接拒绝写入该 Cookie。
  • 场景: 专门用于第三方广告追踪、跨域共享状态、内嵌的第三方 iframe 支付插件等。

3. 三种策略的对比表格

请求类型 示例代码 Strict Lax (默认) None (+Secure)
链接跳转 (GET) <a href="https://site.com"> ❌ 不发送 ✅ 发送 ✅ 发送
预加载 (GET) <link rel="prerender" href="..."> ❌ 不发送 ✅ 发送 ✅ 发送
表单提交 (GET) <form method="GET" action="..."> ❌ 不发送 ✅ 发送 ✅ 发送
表单提交 (POST) <form method="POST" action="..."> ❌ 不发送 ❌ 不发送 ✅ 发送
图片/脚本加载 <img src="...">, <script src="..."> ❌ 不发送 ❌ 不发送 ✅ 发送
框架嵌套 <iframe src="..."> ❌ 不发送 ❌ 不发送 ✅ 发送
异步请求 fetch("..."), axios.get("...") ❌ 不发送 ❌ 不发送 ✅ 发送

4. 如何在服务器端设置?

在 HTTP 响应头(Response Headers)中,通过 Set-Cookie 来指定:

HTTP

复制代码
# 严格模式
Set-Cookie: sid=abc123; SameSite=Strict; Secure

# 默认的宽松模式
Set-Cookie: sid=abc123; SameSite=Lax

# 允许第三方使用(必须带 Secure)
Set-Cookie: sid=abc123; SameSite=None; Secure

5. 总结与开发建议

  1. 敏感操作防范: 涉及修改用户数据、资金安全、核心业务的 Cookie,尽量设为 Strict
  2. 常规会话(Session ID): 保持默认的 Lax 即可,既能防御绝大多数 POST/AJAX 形式的 CSRF 攻击,又不会破坏正常的链接跳转体验。
  3. 跨域共享: 如果你的系统是分布式架构,且使用了不同的一级域名(比如微服务 A 域名是 aaa.com,B 域名是 bbb.com),且需要跨域携带 Cookie,必须使用 SameSite=None; Secure,并确保全站走 HTTPS。
相关推荐
ん贤1 小时前
Higress 详细笔记
笔记·云原生·higress
不羁的木木1 小时前
ArkWeb实战学习笔记04-JavaScript与Native通信
笔记·学习·harmonyos
都市放羊2 小时前
网络小白自学网工——因特网与网络互联技术
网络·笔记·自学
東隅已逝,桑榆非晚2 小时前
新手入门指南:认识 C 语言文件操作(上)
c语言·开发语言·笔记
暴躁小师兄数据学院2 小时前
【AI大数据工程师特训笔记】第08讲:集合运算与超级函数
大数据·笔记·sql·ai·postgresql
searchforAI3 小时前
我的Obsidian知识库,现在可以自动剪藏笔记到本地了
人工智能·笔记·学习·音视频·ai工具·obsidian·视频总结
lcj25113 小时前
vector的基本使用 + 手搓成员变量 size capacity begin end operator[] reserve扩容 拷贝构造 赋值析构
开发语言·c++·笔记·面试
天行健王春城老师3 小时前
制造业生产管控实操指南 PMC体系落地与优化技巧解析
笔记·制造
Eric 辰东4 小时前
【C 语言程序的编译和链接】详解编译链接过程
c语言·笔记·算法·学习方法