在 Web 安全领域,跨站请求伪造(CSRF)长期占据 OWASP Top 10 的一席之地。攻击者诱导已登录用户在不知情的情况下向目标站点发送恶意请求,从而完成转账、改密、发帖等敏感操作。传统的防御手段包括 CSRF Token、验证 Referer/Origin 头、双重 Cookie 校验等,而 SameSite Cookie 属性的出现,为浏览器层面提供了一道原生防线。然而,如果配置不当,这道防线可能形同虚设,甚至引入新的安全问题。
一、CSRF 攻击的本质
要理解 SameSite 的价值,先要看清 CSRF 的成因。浏览器在向某个域发送请求时,会自动携带该域下的 Cookie,无论这个请求是由目标站点自身发起,还是由第三方站点诱导发起。攻击者正是利用了这一“自动携带”机制:
<!-- 攻击者页面中的隐藏表单 -->
<form action="https://bank.com/transfer" method="POST">
<input type="hidden" name="to" value="attacker">
<input type="hidden" name="amount" value="10000">
</form>
<script>document.forms[0].submit();</script>
用户一旦访问该页面,浏览器就会带着 bank.com 的会话 Cookie 发出转账请求。服务端看到合法的会话,便执行了操作。问题的根源在于:服务端无法区分这个请求是用户主动发起的,还是被第三方“借刀杀人”。
二、SameSite 属性的三种取值
SameSite 是 Cookie 的一个属性,用来指示浏览器在跨站请求中是否发送该 Cookie。它有三个取值:
- Strict:最严格。任何跨站请求都不会携带该 Cookie。用户从外部链接点击进入目标站点时,首次请求也不会带上 Cookie,可能导致已登录用户显示为未登录状态。
- Lax:默认值(现代浏览器)。跨站的顶级导航(如点击链接、GET 表单提交)会携带 Cookie,但跨站的 POST 请求、iframe 嵌入、AJAX 请求、图片加载等不会携带。
- None:显式允许跨站携带,但必须同时设置
Secure属性(即只能通过 HTTPS 传输)。否则浏览器会直接拒绝该 Cookie。
三、正确配置的核心原则
1. 会话 Cookie 优先使用 Lax 或 Strict
对于承载身份认证的会话 Cookie,推荐设置为 SameSite=Lax。它在安全性和可用性之间取得了良好平衡:跨站 POST 被拦截,而用户从搜索引擎或外部链接正常访问不受影响。对于安全性要求极高的场景(如网银、管理后台),可以使用 SameSite=Strict,代价是外部链接进入时需要重新登录或做一次跳转。
Set-Cookie: SESSIONID=abc123; Path=/; Secure; HttpOnly; SameSite=Lax
注意,HttpOnly 与 SameSite 是互补的:前者防止 XSS 窃取 Cookie,后者防止 CSRF 滥用 Cookie,两者应同时启用。
2. 谨慎使用 SameSite=None
SameSite=None 意味着放弃浏览器层面的 CSRF 防护。只有在确实需要跨站携带 Cookie 的场景下才应使用,例如:
- 第三方支付回调页面需要读取会话
- 嵌入到其他站点的 Widget 需要认证
- 跨域单点登录(SSO)流程
即便如此,也必须配合其他防御措施,绝不能把 None 当作省事的默认选项。设置 None 时务必同时加上 Secure,且站点必须全站 HTTPS。
3. 不要把 SameSite 当作唯一防线
SameSite 是纵深防御中的一层,而非全部。原因有三:
- 老旧浏览器可能不支持该属性,会直接忽略,等于没有防护。
- Lax 模式下,顶级 GET 导航仍会携带 Cookie,如果服务端用 GET 执行敏感操作,依然存在风险。
- 子域之间的请求通常被视为同站(same-site),恶意子域可能绕过限制。
因此,CSRF Token 仍然应该是核心防御手段。SameSite 的作用是降低攻击面、提供兜底保护。
四、常见配置误区
误区一:认为设置了 Lax 就万无一失。 前面提到,Lax 允许顶级 GET 导航携带 Cookie。如果服务端存在 GET /delete?id=1 这类不安全的接口,攻击者只需诱导用户点击链接即可完成 CSRF。正确做法是:敏感操作一律使用 POST,并校验 CSRF Token。
误区二:全站 Cookie 统一设成 Strict。 这会导致用户从邮件、聊天工具、搜索引擎点进来的第一个请求丢失登录态,体验极差。合理策略是按用途区分:会话 Cookie 用 Lax,真正敏感的一次性令牌用 Strict。
误区三:忽略 Secure 与 None 的绑定关系。 只写 SameSite=None 而不加 Secure,Chrome 等浏览器会直接丢弃该 Cookie,导致功能异常。排查时容易被误判为“Cookie 丢失”问题。
误区四:只在前端设置,忽略服务端下发。 Cookie 的 SameSite 属性由服务端在 Set-Cookie 响应头中声明,前端 JavaScript 无法修改已有 Cookie 的该属性。因此必须在服务端框架或反向代理层统一配置。
五、与其他防御手段的协同
一个完整的 CSRF 防御体系应当分层构建:
- SameSite Cookie:浏览器层的第一道闸门,拦截大部分跨站自动请求。
- CSRF Token:服务端校验请求来源的合法性,是核心防线。Token 应随机、一次性、绑定会话。
- Origin / Referer 校验:作为补充校验,拒绝来源异常的请求。
- 自定义请求头:要求 AJAX 请求携带
X-Requested-With等自定义头,简单表单无法伪造。 - 关键操作二次验证:转账、改密等操作要求输入密码或验证码。
需要强调的是,XSS 与 CSRF 常常被混淆。XSS 是攻击者在页面中注入并执行脚本,可以直接读取页面内容甚至绕过 CSRF Token;SQL 注入则发生在服务端数据层。三者防御手段不同,但都属于 Web 安全加固的必修课。SameSite 无法防御 XSS,也无法防御 SQL 注入,它只解决“跨站请求自动携带凭证”这一个具体问题。
六、实践建议
- 新项目默认将会话 Cookie 设为
SameSite=Lax; Secure; HttpOnly。 - 需要跨站的场景显式声明
SameSite=None; Secure,并同步部署 CSRF Token。 - 在反向代理(如 Nginx)或应用框架中统一注入属性,避免遗漏。
- 上线前用浏览器开发者工具的 Application 面板检查 Cookie 的实际属性。
- 对不支持 SameSite 的老旧客户端做好兼容与降级方案。
结语
SameSite Cookie 是一项低成本、高收益的安全特性,它把部分 CSRF 防御责任从应用层前移到了浏览器层。但它的定位是“纵深防御的一环”,而非“银弹”。只有理解 Strict、Lax、None 三者的语义差异,结合实际业务场景合理选择,并与 CSRF Token、Origin 校验等手段协同使用,才能构建真正可靠的防护体系。安全加固从来不是单一配置的胜利,而是多层防线共同作用的结果。
未经允许不得转载:任鹏个人博客 » SameSite Cookie 在 CSRF 防御中的正确配置方式


朋友圈点赞图在线生成源码