Cookie、Session、Token 到底有什么区别?

专栏:AI 全栈开发|10

|--------------------------------------------------------------------------------------------------------------------------------------|
| 上一篇我们已经把 REST API 的资源、Method 和状态码设计好了,但还有一个问题没解决:`GET /me` 到底怎么知道请求来自谁?这一篇先不讲 JWT 细节和 OAuth,只把 Cookie、Session、Token 三个最容易混的概念真正拆开。 |

一、为什么登录成功一次,下一次请求还要"证明你是谁"

用户输入账号密码,服务器验证成功,这只能说明这一次登录请求通过了。

后面用户再请求:

复制代码
GET /me
GET /orders
POST /checkout

这些请求本身不会自动带着"刚才登录成功"的记忆。

HTTP 的请求语义本身是无状态的:服务器不能仅凭"这是下一条 HTTP 请求"就知道它和上一条是不是同一个登录用户。

所以应用需要一种可验证的标记,让后续请求能重新建立身份上下文。

二、先把三个词摆正位置

图 1 Cookie、Session、Token 不在同一层级:一个是浏览器状态机制,一个是服务端会话状态,一个是凭证形式

Cookie:浏览器怎么保存并自动携带一小段数据

服务器可以通过 Set-Cookie 响应头让浏览器保存 Cookie。后续请求满足 Domain、Path、SameSite、Secure 等条件时,浏览器会自动携带对应 Cookie。

Session:服务器怎么保存一段会话状态

Session 通常表示服务端保存的"这次会话是谁、状态是什么"。浏览器往往只拿一个随机 session id,真正的用户状态留在服务器。

Token:客户端拿什么凭证来证明身份或权限

Token 是一种凭证。它可以是 JWT 这种带 claims 的自包含形式,也可以只是一个随机字符串(opaque token),服务器再去查存储或做 introspection。

|-------------------------------------------------------------------------------------|
| 最容易记错的一点:Token 不等于 JWT;Token 也不等于一定放 localStorage。Token 完全可以放在 HttpOnly Cookie 里发送。 |

三、Cookie 到底是怎么工作的

登录成功后,服务器可以返回:

|----------------------------------------------------------------|
| Set-Cookie: sid=abc123; Path=/; HttpOnly; Secure; SameSite=Lax |

浏览器收到以后,会按 Cookie 规则保存它。后续访问匹配的 URL 时,浏览器自动发送:

|--------------------|
| Cookie: sid=abc123 |

所以 Cookie 的价值主要在"浏览器帮你保存并按规则带回服务器"。

它本身不规定 sid 代表什么。你可以放 session id,也可以放偏好设置;在某些设计里也可以放认证 token。

四、Session:Cookie 里通常只放"钥匙"

图 2 常见 Cookie Session:浏览器带 session id,服务器用它查真正的会话状态

最常见的 Session 登录是:

• 服务器验证账号密码。

• 生成随机 session id。

• 服务端保存 session_id → user_id / expires_at / roles...。

• 把 session id 放进 Cookie。

• 后续请求带 Cookie,服务器查 Session Store,重新得到当前用户。

所以 Cookie 和 Session 经常一起出现:

Cookie 负责运送钥匙;Session 负责保存钥匙背后的可信状态。

五、Session 状态一定要放 Redis 吗

不一定。

学习 Demo 可以放进程内存;小型单实例应用也可能放数据库;多实例服务如果每台机器都要识别同一个 session,就需要共享存储、粘性会话,或者其他能让状态一致的设计。

Redis 是常见实现之一,但不是 Session 的定义。

真正应该先问的是:

• 哪些状态必须在服务器保存?

• 部署多个实例以后,哪些实例需要读到同一份状态?

• Session 过期、退出登录、踢人下线时怎么删除或失效?

六、Token:为什么不能简单等于"无状态 JWT"

图 3 Token 有不同实现:JWT 是一种,opaque token 也是一种;它们的验证方式不同

JWT 很常见,所以很多教程会直接把 Token 和 JWT 画等号。这个习惯容易把基础概念学歪。

Token 更宽泛:

自包含 Token

例如 JWT。凭证里带有 claims、过期时间等,服务器验证签名等信息后可以直接得到一部分身份数据。

Opaque Token

客户端看到的只是随机字符串。服务器收到以后,需要查自己的 Token Store,或者去授权服务器 introspection,才能知道它代表谁。

因此"Token 验证一定不查数据库"并不成立;只有某些自包含 token 设计才可能不为每次请求查询会话记录。

七、Token 到底放哪里

另一个很常见的误区是:

Session → Cookie,Token → localStorage + Authorization。

这不是固定规则。

Token 可以:

• 放在 Authorization: Bearer ... 里,由 JavaScript / 客户端显式发送。

• 放在 HttpOnly Cookie 里,由浏览器自动发送。

• 原生 App 还可能放系统安全存储,再加到请求头。

选哪里取决于客户端类型、XSS / CSRF 风险模型、跨域架构和后端接口设计。完整 Auth 安全会在后面的安全章节展开。

八、HttpOnly、Secure、SameSite 到底各解决什么

|----------|------------------------------|--------------------|
| 属性 | 主要作用 | 不要误解成 |
| HttpOnly | 禁止页面 JavaScript 直接读取该 Cookie | "有它就不会受 XSS 影响" |
| Secure | 只通过安全连接发送 Cookie | "自动解决所有中间人/应用安全问题" |
| SameSite | 限制 Cookie 在部分跨站请求中的携带方式 | "开启以后 CSRF 就彻底消失" |

这些属性都很重要,但它们各自只解决一部分风险。

例如 HttpOnly 能降低认证 Cookie 被脚本直接窃取的风险,但如果页面本身发生 XSS,攻击脚本仍可能借用户身份发起操作。SameSite 能显著降低很多 CSRF 场景,但复杂跨站登录、第三方集成仍要具体设计。

九、用最小 FastAPI 代码看懂 Cookie Session

这一篇不实现完整密码系统,只演示 Session 关系:

复制代码
import secrets
from fastapi import FastAPI, Cookie, HTTPException, Response

app = FastAPI()
sessions: dict[str, str] = {}

@app.post("/login")
def login(response: Response):
    user_id = "u_1001"  # 假设账号密码已经验证成功

    sid = secrets.token_urlsafe(32)
    sessions[sid] = user_id

    response.set_cookie(
        "sid",
        sid,
        httponly=True,
        secure=True,
        samesite="lax",
    )
    return {"ok": True}

@app.get("/me")
def me(sid: str | None = Cookie(default=None)):
    user_id = sessions.get(sid or "")
    if not user_id:
        raise HTTPException(401, "not logged in")

    return {"user_id": user_id}

从这段代码只看一件事:浏览器只有 sid,服务器才保存 sid → user_id 的映射。

这已经足够理解 Cookie Session,不需要在第 10 篇同时实现注册、密码哈希、Redis、滑动过期、JWT 和 OAuth。

十、Cookie、Session、Token 应该怎么对比

|-----------|----------------|-----------------------|---------------------------------|
| 问题 | Cookie | Session | Token |
| 是什么 | 浏览器的 HTTP 状态机制 | 服务端会话状态 | 认证/授权凭证的一种形式 |
| 主要存在哪里 | 浏览器 | 服务器 | 客户端持有;验证信息可能在 token 内,也可能在服务端 |
| 常见传输 | Cookie 头 | session id 常通过 Cookie | Authorization Header 或 Cookie 等 |
| 是否一定可主动吊销 | 取决于里面放什么 | 通常容易通过删除服务端状态吊销 | 取决于 token 设计与验证策略 |
| 是否等于登录方案 | 不是 | 不是单独协议 | 不是 |

十一、这一篇先不要做"Session vs Token 二选一"

真实产品经常组合使用:

• Web 后台使用 Cookie + Server Session。

• API 客户端使用 Bearer Token。

• 浏览器也可以把短期 Token 放 HttpOnly Cookie。

• OAuth 流程最终也可能得到 access token,再由客户端携带。

所以这一篇真正要建立的不是"哪个更好",而是先把三个概念的层级分清。

十二、几个最容易学错的说法

• 误区 1:Cookie、Session、Token 是三个并列登录方案。它们处在不同层级,可以组合。

• 误区 2:Cookie 里放 user_id,服务器直接信任就行。客户端可修改的数据不能直接当可信身份。

• 误区 3:Token 就是 JWT。JWT 只是 Token 的一种实现。

• 误区 4:Token 一定放 localStorage。它也可以通过 Cookie 传输。

• 误区 5:Token 一定完全无状态、一定无法吊销。Opaque Token 本来就依赖服务端状态;JWT 也可以通过黑名单、版本号等引入吊销机制。

• 误区 6:HttpOnly + Secure + SameSite 就等于认证安全完成。它们只是 Cookie 安全设计的一部分。

十三、下一篇

下一篇 11《HTTP Streaming 为什么对 AI 应用这么重要?》会换到另一条 Web 基础线:为什么模型生成 10 秒,页面却不应该白等 10 秒?HTTP Response 怎样边生成边返回,Browser 又怎样一块块消费这些数据?

相关推荐
林伽一27 分钟前
林伽一 · AI科技研报 | 2026年08月第4周
人工智能·科技
yychen_java1 小时前
九:Text-to-SQL 智能数据查询与 Human-in-the-Loop 人机协作
java·人工智能·架构
AI科技先锋报1 小时前
AI数据资产管理平台全景洞察:从治理基座到智能体应用
大数据·人工智能
章老师说1 小时前
BFE v1.8.6 正式发布:AI 网关计费精细化、Claude 协议与会话亲和性升级
运维·人工智能·ai·负载均衡·ai-native
冬奇Lab1 小时前
一天一个开源项目(第206篇):T3 Code - AI 编程 Agent 的统一控制台
人工智能·开源·资讯
IT古董1 小时前
AI 资讯日报 | 2026年9月1日 :混元 Hy4 开源、DeepSeek 多模态登顶、可灵获国家队 14 亿注资
人工智能·开源
冬奇Lab1 小时前
Code Agent 解剖(18):AgentTeams——TeamFanout 与 TeamCollect 的并行机制
人工智能
ai小陈1 小时前
FramePack图生视频云端部署实战:从单图输入到视频输出的完整流程
服务器·人工智能·安全·ai·音视频·gpu算力
程序员-Benothing2 小时前
OpenAI断供Cursor:当AI巨头开始“清理门户“,开源生态的中立性还能撑多久?
人工智能·开源·大模型