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。
相关推荐
噜~噜~噜~10 小时前
操作系统笔记-3.1.1.3 进程的内存映像
笔记·操作系统
摇滚侠10 小时前
《Spring Boot 3:高级与架构设计》第 2 章 IOC容器的高级机制 Environment 阅读笔记 4
spring boot·笔记·后端
李帅朋19 小时前
微分基本定义笔记
人工智能·笔记·深度学习·神经网络
xian_wwq1 天前
【学习笔记】深度认知系列-第16讲-提示词工程
人工智能·笔记·学习
youm20031 天前
认识Redis
redis·笔记·学习
亮工硬件1 天前
1-11 STM32内部FLASH(数据掉电保存)
笔记·stm32·单片机·嵌入式硬件·学习
疯狂打码的少年1 天前
【数据库技术】复习日:关系代数 + SQL + 规范化(整理对比表)
jvm·数据库·笔记·sql
维克兜率天1 天前
【维克】特征归一化与标准化:为什么模型对数据的“尺度“很敏感?
人工智能·笔记·python·机器学习·量化
摇滚侠1 天前
《SpringBoot 3:入门与应用实战》第 12 章 JDBC 与事务 使用 JdbcTemplate 阅读笔记 31
android·spring boot·笔记
金字塔頂の蝸牛1 天前
商务日语口语全手册(一)
笔记·日语·语言·外语