不喜欢广告? 无广告 今天

HTTP Cookie 如何正确构建和解析它们

发布日期
HTTP Cookie:如何正确构建和解析它们 1
广告 移除?

HTTP Cookie无处不在。每一个登录会话、购物车和分析工具都依赖它们。然而,大多数开发者只是复制粘贴一个头部,然后就不再深入理解这些属性实际的作用——或者当它们使用错误时会发生什么。 Set-Cookie 本指南涵盖了Cookie的结构、每一个有意义的属性、如何解析Cookie字符串,以及为什么

是你的CSRF防御。如果你希望立即动手实践,可以尝试 SameSite IO Tools Cookie Parser Cookie BuilderCookie的实际外观.

当服务器想要设置一个Cookie时,它会发送一个

响应头: Set-Cookie 浏览器会存储这个信息,并在后续请求中将其发送回来作为:

Set-Cookie: sessionId=abc123; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=86400

这就是整个机制。复杂性在于这些属性。

Cookie: sessionId=abc123

Cookie结构:分解字符串

一个Cookie字符串遵循一致的格式:

对是第一个部分。第一个分号之后的所有内容是浏览器的指令——服务器在接收到的

name=value; attribute1; attribute2=attributeValue; ...

name=value 头中永远不会看到这些属性。 Cookie 您必须正确设置的安全属性

HttpOnly

防止JavaScript通过

HttpOnly 读取Cookie。这是防范XSS攻击窃取会话令牌的直接防御措施。 document.cookie任何用于用户身份验证的Cookie都应设置

Set-Cookie: sessionId=abc123; HttpOnly

。没有充分的理由不这样做。 HttpOnly表示浏览器仅在HTTPS连接中发送该Cookie。如果没有它,Cookie将以明文形式通过HTTP传输,可能被拦截。在生产环境中,会话Cookie始终需要

安全的

Secure 。在本地开发环境中使用 Secure时,可以省略它——浏览器对localhost会做出例外。 http://localhost控制浏览器在跨站请求中是否包含Cookie。这是防范CSRF攻击的主要防御措施。三个值:

SameSite

SameSite ——Cookie不会在跨站请求中发送。最安全,但用户点击来自邮件的链接时会登出(该Cookie不会在初始导航中发送)。

  • Strict ——Cookie在来自外部站点的顶级导航(GET请求)中发送,但不会在嵌入式跨站请求或跨站POST请求中发送。这是没有显式
  • Lax 属性的Cookie的浏览器默认设置。 SameSite ——Cookie在所有跨站请求中发送。适用于第三方Cookie(OAuth流程、嵌入式组件)。必须与
  • None 搭配使用。 Secure.
# Third-party / cross-site cookie (e.g., OAuth callback)
Set-Cookie: token=xyz; SameSite=None; Secure

如果发送 SameSite=None 没有 Secure,现代浏览器将完全拒绝该Cookie。对于大多数会话Cookie,使用 SameSite=Lax ——它在安全性和可用登录体验之间取得了平衡。

作用域:域名和路径

Domain

Domain 属性指定了哪些主机名会接收该Cookie。

Set-Cookie: user=alice; Domain=example.com

使用 Domain=example.com时,Cookie将发送到 example.com 及其所有子域名(api.example.com, app.example.com)。如果没有 Domain 属性,Cookie仅发送到设置它的精确来源——不会发送到子域名。

常见误解:设置 Domain=example.com 并不会将Cookie限制在仅 不是 。它会扩展作用域以包含子域名。如果希望仅限单个主机,应省略该属性。 example.com限制触发Cookie发送的URL路径。

小路

Path 该Cookie仅随对

Set-Cookie: adminToken=xyz; Path=/admin

及其路径以下的请求一起发送。对 /admin 的请求不会包含它。默认值是 //api ,表示所有路径。 /Max-Age 与 Expires

两者都控制Cookie过期时间。优先使用

采用绝对日期格式的HTTP日期。这是相对于客户端时钟的,而你无法控制它。 Max-Age.

  • Expires 采用从现在起的秒数:
  • Max-Age 表示24小时。相对于服务器的意图,而不是客户端的时钟。 Max-Age=86400 当两者都存在时,

优先。没有这两个属性的Cookie是 Max-Age 会话Cookie ——它在浏览器关闭时消失。 Cookie属性参考

属性

作用阻止JavaScript访问该Cookie默认推荐
HttpOnly未设置始终设置用于身份验证的Cookie仅通过HTTPS传输
Secure生产环境中始终设置始终设置用于身份验证的Cookie控制跨站发送
SameSite宽松(现代浏览器)会话使用宽松;第三方使用无 + 安全设置主机名范围
Domain仅当前主机除非需要跨子域名访问,否则省略设置路径范围
Path除非需要隔离管理员令牌,否则保留为 //过期前的秒数
Max-Age会话Cookie优先于Expires绝对过期日期
Expires使用Max-Age代替优先于Expires设置Cookie在代码中的方法

Node.js(Express)

Python(FastAPI)

app.post('/login', (req, res) => {
  // ... verify credentials ...

  res.cookie('sessionId', token, {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'lax',
    maxAge: 86400 * 1000, // milliseconds in Express
    path: '/',
  });

  res.json({ ok: true });
});

手动解析Cookie头

from fastapi import FastAPI, Response

app = FastAPI()

@app.post("/login")
def login(response: Response):
    # ... verify credentials ...

    response.set_cookie(
        key="sessionId",
        value=token,
        httponly=True,
        secure=True,
        samesite="lax",
        max_age=86400,
        path="/",
    )
    return {"ok": True}

服务器接收到的

Cookie 头中仅包含 name=value 对,以 ; :

Cookie: sessionId=abc123; theme=dark; lang=en

分隔。手动解析时:以 ; (分号加空格)分割,然后以 第一个 = 仅分割。需要了解的一些边缘情况:

  • 值可以包含 = (基64字符串常见)——始终以第一个 = 分割
  • Cookie名称是大小写敏感的
  • 分隔符周围的空白可能变化——防御性地修剪两边

与其自行编写分割逻辑,不如使用 Cookie Builder 来解码任何 Cookie 头并检查每个值,或使用 IO Tools Cookie Builder 来构造一个具有正确属性的 Set-Cookie 头。

Cookie与CSRF

跨站请求伪造利用了浏览器自动在请求到某个域名时包含Cookie的事实,即使该请求由另一个站点发起。一个位于 evil.com 的恶意页面可以向 bank.com/transfer提交一个表单,如果用户已登录,浏览器会随伪造请求发送其会话Cookie。

SameSite=Lax 阻止了大多数CSRF攻击向量,因为跨站POST请求——典型的攻击模式——不会包含Cookie。 SameSite=Strict 更加彻底,但可能影响用户体验。

CSRF令牌作为纵深防御仍然有效,特别是在高风险操作中,以及当 SameSite=None 是第三方上下文所必需时。这两种防御措施相辅相成。

想要享受无广告的体验吗? 立即无广告

安装我们的扩展

将 IO 工具添加到您最喜欢的浏览器,以便即时访问和更快地搜索

添加 Chrome 扩展程序 添加 边缘延伸 添加 Firefox 扩展 添加 Opera 扩展

记分板已到达!

记分板 是一种有趣的跟踪您游戏的方式,所有数据都存储在您的浏览器中。更多功能即将推出!

广告 移除?
广告 移除?
广告 移除?

新闻角 包含技术亮点

参与其中

帮助我们继续提供有价值的免费工具

给我买杯咖啡
广告 移除?