乐闻世界logo
搜索文章和话题

SameSite Cookie 属性如何防止 CSRF 攻击?

2月19日 19:35

SameSite Cookie 属性是防御 CSRF 攻击的重要机制,它控制 Cookie 在跨站请求中的发送行为。

SameSite 属性概述

SameSite 是 Cookie 的一个属性,用于指示浏览器是否应该在跨站请求中发送该 Cookie。它有三个可选值:StrictLaxNone

属性值详解

1. SameSite=Strict

行为

  • 只在同站请求中发送 Cookie
  • 跨站请求(包括导航)都不会发送 Cookie

适用场景

  • 银行、支付等高安全性应用
  • 敏感操作(如转账、修改密码)
  • 不需要跨站功能的应用

示例

javascript
// 设置 SameSite=Strict document.cookie = 'sessionid=abc123; SameSite=Strict; Secure; HttpOnly';

优点

  • 提供最强的 CSRF 防护
  • 完全阻止跨站请求携带 Cookie

缺点

  • 用户从外部链接进入时需要重新登录
  • 可能影响用户体验

2. SameSite=Lax(推荐)

行为

  • 允许某些跨站请求发送 Cookie
  • 阻止大多数 CSRF 攻击

允许的跨站请求

  • 顶级导航(GET 请求)
  • 链接跳转(<a> 标签)
  • 表单 GET 请求

阻止的跨站请求

  • POST 请求(表单提交)
  • AJAX 请求
  • <iframe><img><script> 等资源加载

示例

javascript
// 设置 SameSite=Lax document.cookie = 'sessionid=abc123; SameSite=Lax; Secure; HttpOnly';

适用场景

  • 大多数 Web 应用
  • 需要外部链接跳转的应用
  • 平衡安全性和用户体验

优点

  • 提供良好的 CSRF 防护
  • 用户体验较好
  • 现代浏览器默认值

缺点

  • 某些跨站 POST 请求可能受影响
  • 需要确保应用兼容性

3. SameSite=None

行为

  • 允许所有跨站请求发送 Cookie
  • 必须配合 Secure 属性使用

示例

javascript
// 设置 SameSite=None document.cookie = 'sessionid=abc123; SameSite=None; Secure; HttpOnly';

适用场景

  • 需要跨站功能的应用
  • 第三方登录(如 OAuth)
  • 嵌入式内容

优点

  • 不影响现有跨站功能
  • 兼容旧应用

缺点

  • 无法防御 CSRF 攻击
  • 需要其他防护措施

浏览器支持情况

主流浏览器支持

  • Chrome:51+ 版本支持,80+ 版本默认 Lax
  • Firefox:60+ 版本支持
  • Safari:12+ 版本支持
  • Edge:79+ 版本支持
  • Opera:39+ 版本支持

兼容性处理

javascript
// 检测浏览器是否支持 SameSite function setCookie(name, value, days) { let expires = ''; if (days) { const date = new Date(); date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); expires = '; expires=' + date.toUTCString(); } // 现代浏览器 let sameSite = '; SameSite=Lax'; // 旧版浏览器不支持 SameSite const cookieString = name + '=' + value + expires + sameSite + '; path=/; Secure; HttpOnly'; document.cookie = cookieString; }

同站与跨站的定义

同站(Same-Site)

  • 相同的顶级域名(eTLD+1)
  • 例如:
    • https://example.comhttps://www.example.com 是同站
    • https://app.example.comhttps://api.example.com 是同站

跨站(Cross-Site)

  • 不同的顶级域名
  • 例如:
    • https://example.comhttps://evil.com 是跨站
    • https://example.comhttps://example.net 是跨站

实际应用示例

1. 银行应用(Strict)

javascript
// 高安全性要求 document.cookie = 'sessionid=abc123; SameSite=Strict; Secure; HttpOnly; Max-Age=3600';

2. 电商网站(Lax)

javascript
// 平衡安全性和用户体验 document.cookie = 'sessionid=abc123; SameSite=Lax; Secure; HttpOnly; Max-Age=86400';

3. 第三方登录(None)

javascript
// 需要跨站功能 document.cookie = 'oauth_token=xyz789; SameSite=None; Secure; HttpOnly; Max-Age=3600';

框架集成

Express.js

javascript
app.use(session({ secret: 'your-secret', cookie: { secure: true, httpOnly: true, sameSite: 'lax' } }));

Spring Boot

java
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) .and() .csrf() .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()); } }

Django

python
# settings.py SESSION_COOKIE_SECURE = True SESSION_COOKIE_HTTPONLY = True SESSION_COOKIE_SAMESITE = 'Lax' CSRF_COOKIE_SECURE = True CSRF_COOKIE_HTTPONLY = True CSRF_COOKIE_SAMESITE = 'Lax'

常见问题

1. SameSite=None 不生效

原因:缺少 Secure 属性 解决:必须同时设置 Secure 属性

javascript
// 错误 document.cookie = 'sessionid=abc123; SameSite=None'; // 正确 document.cookie = 'sessionid=abc123; SameSite=None; Secure';

2. 跨站 POST 请求失败

原因:SameSite=Lax 阻止了跨站 POST 请求 解决

  • 使用 SameSite=None(需要其他 CSRF 防护)
  • 改用同站请求
  • 使用 CSRF Token

3. 第三方登录失败

原因:SameSite 属性阻止了跨站 Cookie 解决

  • 为特定 Cookie 设置 SameSite=None
  • 使用 OAuth 2.0 的授权码模式
  • 使用 PostMessage 通信

最佳实践

1. 默认使用 SameSite=Lax

javascript
// 大多数应用的最佳选择 document.cookie = 'sessionid=abc123; SameSite=Lax; Secure; HttpOnly';

2. 敏感操作使用 SameSite=Strict

javascript
// 高安全性要求 document.cookie = 'admin_session=xyz789; SameSite=Strict; Secure; HttpOnly';

3. 避免 SameSite=None

javascript
// 尽量避免,除非必要 // 如果必须使用,配合其他防护措施 document.cookie = 'third_party_token=abc123; SameSite=None; Secure; HttpOnly';

4. 配合其他防护措施

  • CSRF Token
  • Origin/Referer 验证
  • 自定义请求头

5. 测试兼容性

  • 在不同浏览器中测试
  • 测试跨站场景
  • 测试第三方集成

总结

SameSite Cookie 属性是防御 CSRF 攻击的有效手段。推荐使用 SameSite=Lax 作为默认配置,它在提供良好 CSRF 防护的同时保持良好的用户体验。对于高安全性要求的应用,可以使用 SameSite=Strict。尽量避免使用 SameSite=None,除非确实需要跨站功能,并配合其他防护措施。

标签:CSRF