HTTP Cookie解析

这张图把 HTTP Cookie 讲成了三件事:HTTP 为什么"无状态"Cookie 如何给 HTTP "加状态" 、以及 Cookie 的隔离规则和关键属性。我按图的四块区域逐一拆开说明。


1) 左上:为什么说 HTTP 是 Stateless(无状态)

HTTP 协议层面把每次请求都当成"独立事件":

  • 浏览器先发 GET /foo

  • 过一会又发 GET /bar

对服务器来说,这两次请求之间没有"天然绑定关系" 。如果请求里不带任何"身份/上下文",服务器就只能每次都问一句:"你是谁?"

所以图里才写:同一个浏览器来的两个请求,默认也"不相关"。

无状态的好处:协议简单、服务器更容易横向扩展(不必强依赖某台机器的内存状态)。

但坏处:登录态、购物车、偏好设置等"连续交互"需要额外机制维持。


2) 右上:Cookie 如何给 HTTP "加状态"(核心流程)

图右上画的是典型的"首次识别 + 后续自动携带"的闭环:

  1. 浏览器首次自报身份/触发登录(示意:"Hello, I am user ABC")

  2. 服务器生成一个 Cookie (通常是一个随机的 session id,比如 sid=...,或某些轻量信息)

  3. 服务器在响应头里发回:Set-Cookie: ...

  4. 浏览器把 Cookie 存入本地(cookie jar)

  5. 之后浏览器再请求同站点资源时,会自动在请求头里带上:Cookie: ...

  6. 服务器收到后 校验 Cookie(比如查 session 表、验证签名、检查过期时间)

  7. 于是服务器就能说:"我知道你是谁了"

对应到真实 HTTP 头部,大概长这样:

复制代码
HTTP/1.1 200 OK Set-Cookie: sid=RANDOM_TOKEN; Path=/; HttpOnly; Secure; SameSite=Lax 

后续请求:

复制代码
GET /bar HTTP/1.1 Host: example.com Cookie: sid=RANDOM_TOKEN 

关键点:Cookie 最大的"威力"不是它能存多少数据,而是"浏览器会自动携带",从而把"状态"粘到每一次请求上。


3) 左下:Cookie Isolation(隔离)是怎么回事

图左下强调:浏览器不会把所有 Cookie 一股脑发给所有服务器------它按规则隔离:

  • 按 Domain 隔离foo.com 的 Cookie 不会发给 bar.com

  • 按 Path 进一步收敛 :只在匹配路径前缀时才发送(例如只对 /api 生效)

  • 按 Secure 限制协议 :标了 Secure 的 Cookie 只会在 HTTPS 请求里发送

所以你会看到图里不同域(Foo/Bar/Qux/Baz)各自有自己的 cookie 集合,互不乱串------这就是"Cookie 罐子"的隔离逻辑。


4) 右下:Cookie Attributes(属性)逐个解释(图里列了 5 个)

图里的属性都非常关键,我按"解决什么问题"来讲:

✅ Secure

  • 含义:Cookie 只能通过 HTTPS 发送(HTTP 明文请求不会带它)

  • 目的:防止在明文链路上被抓包窃取会话(session hijacking)

✅ HttpOnly

  • 含义:Cookie 不能被 JS 读取document.cookie 拿不到)

  • 目的:主要对抗 XSS 窃取会话(即使页面被注入脚本,也更难直接偷走 session cookie)

✅ SameSite

  • 含义:控制 Cookie 在"跨站请求"时是否携带

  • 目的:主要对抗 CSRF

  • 常见值(简化理解):

    • Strict:最严格,跨站一律不带

    • Lax:折中,很多"顶级导航 GET"允许带(现代浏览器默认趋向 Lax)

    • None:允许跨站携带(通常要求同时 Secure,否则浏览器可能拒收)

这就是图里写的:"控制 cookie 能否随 cross-site 请求发送"。

✅ Domain

  • 含义:指定哪些域/子域可以接收此 Cookie

  • 例:Domain=example.com 往往意味着 a.example.comb.example.com 也能带

  • 目的:用于"同一主域下多子系统共享登录态"(但也会扩大攻击面,要谨慎)

✅ Priority

  • 含义:当浏览器存储空间/携带空间紧张时,给 Cookie 排优先级(高优先级更不容易被清理)

  • 目的:让"关键 Cookie(如会话)"更稳定,不被随意淘汰(不同浏览器实现细节可能略有差异)

图里没画但实际非常常用的还有:Expires/Max-Age(生命周期)、Path(路径范围)。


5) "Cookies And Sessions":两者到底什么关系?

很多人会把它们当一回事,但更准确的说法是:

  • Cookie 是浏览器端的"携带机制/存储容器"(小纸条)

  • Session 是服务器端的"状态数据"(档案/登录态/购物车等)

最经典的组合是:
Cookie 里只放一个 session id(随机、不可猜),真正的用户状态放在服务器(内存/Redis/数据库)

这样既能"有状态",又避免把敏感信息直接塞进 Cookie。详情请阅读:

你该了解的Web 存储类型


6) 实战安全建议(非常实用)

如果你在做登录态/鉴权,通常建议:

  • 会话 Cookie: Secure + HttpOnly + SameSite=Lax(或 Strict)

  • 不要把密码/敏感信息直接放 Cookie(Cookie 会随着请求自动发送,泄露成本低)

  • 防 CSRF: SameSite 之外,关键写操作再配合 CSRF Token / 双重提交等

  • 防会话劫持: 全站 HTTPS、短有效期、登录后换 session id、异常设备/IP 风险控制

下面我继续把 Cookie 讲到"工程落地层面":有哪些类型、怎么设计会话、怎么和安全机制配合、以及常见坑


A. Session Cookie(会话 Cookie)

  • 没设置 Expires / Max-Age

  • 浏览器一般在"关闭浏览器/标签策略触发"时清掉(不同浏览器略有差异)

  • 适合:纯登录态、短期状态

B. Persistent Cookie(持久 Cookie)

  • 设置 Max-Age=...Expires=...

  • 适合:记住登录(Remember me)、偏好设置(语言、主题)

实践:真正"记住登录"最好不要把同一个 session 拉很长,而是用 Refresh Token/长期凭证 + 短会话 的方案(下面讲)。


模式 1:只放 Session ID(最推荐)

Cookie 里:sid=random_128bit

  • 服务器:sid -> user_id, roles, expiry, csrf_key ... 存在 Redis/DB

  • 优点:敏感信息不落客户端;可以随时失效;风控好做

  • 缺点:服务端要存状态(但这通常是可接受的)

模式 2:Cookie 里放"签名的状态"(类似 JWT,但别混淆)

Cookie 里:state=base64(payload).base64(sig)

  • 服务器不存或少存,靠签名校验

  • 优点:水平扩展简单

  • 缺点:吊销难(除非加黑名单);payload 泄露风险;尺寸变大

模式 3:混合:短会话 + 刷新凭证

  • sid(短期,10~30 分钟滚动续期)

  • refresh(长期,7~30 天,仅用于换新 sid;更严格校验设备指纹等)

  • 优点:安全与体验平衡最好

  • 缺点:实现稍复杂


9) 登录态(Session)怎么设计才靠谱(推荐模板)

给一个你几乎可以直接照抄的策略:

登录成功返回

复制代码
Set-Cookie: sid=...; Path=/; HttpOnly; Secure; SameSite=Lax Set-Cookie: csrf=...; Path=/; Secure; SameSite=Lax 

解释

  • sidHttpOnly(JS 拿不到,防 XSS 偷会话)

  • csrf不设 HttpOnly(前端需要读出来放到请求头里,配合 CSRF 防护)

  • 两者都 Secure + SameSite=Lax

  • 写操作(POST/PUT/DELETE)要求带:X-CSRF-Token: <csrf cookie value> 或基于表单的 token

这套是经典的"双 Cookie + header"CSRF 防护套路,兼容性和安全性都不错。


10) SameSite 细讲:什么时候必须用 None?

你遇到下面情况,大概率要 SameSite=None; Secure

  • 你的网站需要在 第三方站点的 iframe 里保持登录态

  • 你做 跨站单点登录,登录态要在不同站点间自动带 cookie(很多时候也不行,现代浏览器限制很严)

  • 你确实需要第三方 Cookie(广告、统计那类)

但注意:SameSite=None 会显著增加 CSRF 风险,必须配合 CSRF Token、Referer/Origin 校验等。


默认更安全

不写 Domain:Cookie 只会发给"设置它的那个精确主机名"。

需要共享登录时

如果你有:

  • api.example.com

  • www.example.com

  • admin.example.com

你可能设:
Domain=example.com

风险: 任意子域如果被接管/有 XSS/可设置 Cookie,可能影响主域安全策略(比如 cookie 覆盖、会话固定等)。

所以:能不共享就不共享;真要共享,子域治理要非常严。


12) 常见坑合集(踩过一次就懂)

比如 user=adminrole=superuser ------ 被改了就完蛋。

即使你"以为"浏览器不会让用户改,用户也能用代理/插件/脚本改。

✅ 解决:敏感信息放服务端(Session),或签名/加密并严格校验。

坑 2:漏了 Secure

上了 HTTPS 还漏 Secure,Cookie 可能在误配置/降级场景走明文。

坑 3:CSRF 只靠"用户不点链接"

CSRF 是"用户不知情的跨站请求",必须用 SameSite + Token/Origin 校验。

坑 4:XSS 以为 HttpOnly 就完事

HttpOnly 只能防"偷 cookie",但 XSS 仍能直接发起带 cookie 的请求做坏事。

✅ 解决:CSP、输出编码、依赖治理、敏感操作二次验证等。

坑 5:Cookie 太大/太多

每次请求都会带 cookie,影响性能,还可能触发浏览器/网关限制(例如头部过大 431)。

✅ 解决:Cookie 只放"标识符",别放大 payload。


登录态:

  • sid=<random>; Path=/; HttpOnly; Secure; SameSite=Lax

CSRF:

  • csrf=<random>; Path=/; Secure; SameSite=Lax

退出登录:

  • Set-Cookie: sid=; Max-Age=0; Path=/; ...(同 Path/Domain 必须匹配才能删除)
相关推荐
在路上看风景1 小时前
7.2 认证和报文的完整性
网络
w***48821 小时前
【MySQL】视图、用户和权限管理
android·网络·mysql
007php0071 小时前
nginx加速缓存导致Event-Stream消息延迟问题的解决方案
运维·网络·数据库·nginx·缓存·面试·职场和发展
Evan芙1 小时前
OpenEuler系统网卡地址定制
运维·服务器·网络
拾忆,想起1 小时前
Dubbo序列化方式全解析:从原理到实战的性能优化指南
服务器·网络·微服务·性能优化·架构·dubbo
鲜枣课堂1 小时前
聊聊华为新推出的无网应急通信
网络·华为
心随雨下2 小时前
WebSocket使用注意事项与优化策略
网络·websocket·网络协议
e***28292 小时前
报错The default superclass, “jakarta.servlet.http.HttpServlet“(已经配置好tomcat)
http·servlet·tomcat
WHFENGHE2 小时前
输电线路微气象在线监测装置——电力安全的实时守护者
网络·安全