Featured image of post 安全 Cookie 配置:完整的 Web 开发人员指南Featured image of post 安全 Cookie 配置:完整的 Web 开发人员指南

安全 Cookie 配置:完整的 Web 开发人员指南

安全 cookie 配置的完整指南,涵盖 SameSite、安全标志、HttpOnly、cookie 前缀、CHIPS 和现代 Web 应用程序的跨站点行为。

Cookie 仍然是网络上最常配置错误的安全控制之一。单个缺失的属性可能会使您的应用程序遭受会话劫持、CSRF 或跨站点信息泄漏。现代浏览器已经推出了更严格的默认值,但了解每个属性并正确组合它们对于纵深防御至关重要。

核心安全属性是 SecureHttpOnlySameSite__Host- / __Secure- 前缀。每一个都有不同的目的,当它们结合起来时效果最好。

同一站点属性

SameSite 控制何时在跨站点请求中发送 cookie。它是针对 CSRF 攻击的主要防御措施。

Set-Cookie: session=abc123; SameSite=Lax
价值行为使用案例
占位符_0仅针对同一站点请求发送(顶级导航和子资源)CSRF 代币、敏感账户操作
Lax(默认)发送用于顶级 GET 导航,而不是跨站点 POST、图像、脚本或 iframe常规会话 cookie
占位符_0发送所有跨站点请求;需要 Secure 标志第三方小部件、嵌入式内容、API 集成

SameSite=Lax 是现代浏览器(Chrome、Edge、Firefox)中的默认值,适用于大多数会话 cookie。将 Strict 用于 CSRF 令牌和关键操作。仅当需要第三方嵌入时才使用 None — 并且始终将其与 Secure 配对。


安全标志

Secure 属性确保 cookie 仅通过 HTTPS 传输。如果没有它,cookie 可能会通过未加密的连接被拦截——在公共 Wi-Fi 上尤其危险。

Set-Cookie: session=abc123; Secure

无法从 http:// 源设置此标志。它必须从 HTTPS 页面上下文设置。一个常见的错误是在开发期间在 localhost 上设置 Secure (有效),但使用混合内容进行部署会导致 cookie 在生产中通过 HTTP 提供服务。

使用 SameSite=None 时,Secure 标志是必需的。浏览器拒绝没有 SecureSameSite=None cookie。


仅 Http 属性

HttpOnly 阻止 JavaScript 通过 document.cookie 进行访问。这是针对基于 XSS 的会话盗窃的主要防御措施。 XSS漏洞仍然可以执行任意JavaScript,但攻击者无法直接读取会话cookie。

Set-Cookie: session=abc123; HttpOnly

代价是客户端 JavaScript 无法读取或写入 HttpOnly cookie。对于检查 cookie 的 SPA 身份验证流程,解决方法是使用检查身份验证状态的专用 API 端点,或使用存储在内存中的基于令牌的身份验证。如果可以避免的话,切勿将会话令牌存储在 XSS 可以访问的地方。


路径和域范围

Path 属性将 cookie 限制为特定的 URL 路径。 Domain 属性控制哪些子域接收 cookie。

Set-Cookie: app_session=xyz; Path=/app; Domain=.example.com

对站点范围的 cookie 使用 Path=/ 或限制到特定路径,例如 /admin。如果设置得太宽泛,Domain 属性会很危险。 Domain=.example.com 使所有子域都可以访问 cookie,包括 staging.example.comdev.example.com — 这些子域通常不太安全。仅当明确需要子域共享时才设置广泛的 Domain


Cookie 前缀提供客户端代码无法绕过的协议级保证。

Set-Cookie: __Host-session=abc123; Secure; Path=/
Set-Cookie: __Secure-csrf=xyz; Secure
前缀要求
占位符_0必须是安全的,Path=/,无域属性 — 范围仅限于源
占位符_0必须是安全的 — 范围仅限于具有安全性的域

使用 __Host-session 作为会话令牌。该前缀确保 cookie 的范围仅限于单一来源,从而防止子域攻击。浏览器在协议级别强制执行这些要求——没有 JavaScript 可以去除前缀。


浏览器强制执行限制:每个 cookie 大约 4KB,每个域 50-150 个 cookie,每个源 10-50 个 cookie。通过仅存储引用(会话 ID、资源标识符)而不是将数据直接嵌入 cookie 值来保持在这些限制之内。

CHIPS(具有独立分区状态的 Cookie)引入了 Partitioned 属性。这会为每个顶级站点创建一个单独的 cookie jar,防止跨站点跟踪,同时允许嵌入式第三方服务维护状态。

Set-Cookie: widget_pref=dark; Secure; SameSite=None; Partitioned; Path=/

浏览器支持包括 Chrome 114+、Edge 114+ 和 Opera。 CHIPS 非常适合需要状态但不启用跨站点跟踪的支付 iframe、嵌入式地图和第三方聊天小部件。


跨站点和跨源行为

同站点和同源是影响cookie发送的不同概念。 https://app.example.comhttps://api.example.com 是同一站点(相同的可注册域)但跨源(不同的主机名)。 SameSite 规则在站点上进行评估,而不是在原点进行评估。

对于包含 cookie 的跨源获取请求:

fetch("https://api.example.com/data", {
  credentials: "include",
});

这要求服务器以 Access-Control-Allow-Credentials: true 进行响应。 Safari 的智能跟踪预防 (ITP) 和 Firefox 的增强跟踪保护 (ETP) 对 cookie 生命周期和跨站点访问施加了额外的限制,特别是对于无需用户交互的 cookie。


实用配置菜谱

// Express.js
app.use(session({
  name: "__Host-session",
  secret: process.env.SESSION_SECRET,
  cookie: {
    secure: true,
    httpOnly: true,
    sameSite: "lax",
    path: "/",
  },
}));
// Next.js API route
export async function GET(request) {
  return new Response(JSON.stringify({ ok: true }), {
    headers: {
      "Set-Cookie":
        "session=abc123; HttpOnly; Secure; SameSite=Lax; Path=/",
    },
  });
}
Cookie 类型配置
认证占位符_0
CSRF 代币占位符_0
第三方小部件占位符_0

测试与调试

浏览器开发工具(“应用程序”选项卡)显示所有 cookie、它们的属性以及它们是否标记为安全或 httpOnly。对于命令行测试:

# Check cookie behavior
curl -v -c cookies.txt -b cookies.txt https://example.com/login

网络选项卡的响应标头显示 Set-Cookie 标头。检查所有预期的属性是否都存在。使用 OWASP ZAP 或类似工具进行自动 cookie 安全扫描,作为 CI 管道的一部分。

概括

深度防御 cookie 策略结合了所有可用属性。大多数会话 cookie 的默认建议是 HttpOnly + Secure + SameSite=Lax。对于 CSRF 令牌,请添加 __Host- 前缀和 SameSite=Strict。为不可避免的第三方上下文保留 SameSite=None 。使用浏览器开发工具和自动扫描仪进行定期审核可确保您的 cookie 配置在浏览器不断发展其隐私和安全默认设置时保持安全。