HTTP 完全指南(三):Cookie、Session 与 Token 深度详解

引言

上一篇我们讲了 HTTP 缓存。今天要解决的是 HTTP 最著名的缺陷:无状态。

什么叫无状态?服务器每次收到请求,都把它当成一个全新的请求,完全不记得刚才这个客户端来过没有、做过什么。你登录了淘宝,刷新一下页面,服务器问:"你是谁?请重新登录"------这就是无状态带来的问题。

为了让 HTTP "记住"用户,诞生了三套方案:Cookie 、Session 、Token。它们各自有不同的工作原理和适用场景,本文将逐一深挖。

第一部分:Cookie

一、Cookie 是什么

Cookie 是服务器让浏览器保存在本地的一小段数据 (通常不超过 4KB)。浏览器每次请求该服务器时,会自动带上所有 Cookie。

二、Cookie 的属性

复制代码
Set-Cookie: session_id=abc123; Domain=.example.com; Path=/; Max-Age=3600; HttpOnly; Secure; SameSite=Lax
属性 含义 示例
Name=Value Cookie 的名字和值 session_id=abc123
Domain 允许访问的域名范围 .example.com(所有子域名都能访问)
Path 允许访问的路径范围 /(整个网站);/admin(只管理后台)
Max-Age 存活秒数(相对时间) 3600(1小时后过期)
Expires 过期时间(绝对时间) Mon, 02 Jun 2025 10:00:00 GMT
HttpOnly 禁止 JavaScript 访问 只通过 HTTP 传输,document.cookie 读不到
Secure 只在 HTTPS 连接中传输 HTTP 明文不传输此 Cookie
SameSite 跨站请求控制 Strict / Lax / None

三、HttpOnly 和 Secure 为什么重要

四、SameSite 详解

第二部分:Session

一、Session 是什么

Session 是存储在服务器端 的用户数据。浏览器只保存一个 session_id(通常存在 Cookie 中),服务器根据这个 ID 找到对应的 Session 数据。

二、Session 的存储位置

方式 优点 缺点
内存 最快 重启丢失,不能多服务器共享
文件 重启不丢 慢,不能多服务器共享
Redis 快 + 持久 + 多服务器共享 需要额外部署
数据库 持久可靠 最慢

三、Cookie vs Session

对比 Cookie Session
存储位置 浏览器端 服务器端
安全性 较低(客户端可见) 较高(服务器控制)
容量 约 4KB 无限制
网络开销 每次请求自动带上 只有一个 session_id
服务器压力 无 需要存储和管理
适用场景 记住用户偏好、主题 登录状态、敏感数据

第三部分:Token(JWT)

一、Token 是什么

Token 是一段自包含的加密字符串 ,服务器签发后交给客户端,客户端每次请求手动携带这个 Token。

最流行的 Token 实现是 JWT(JSON Web Token)。

二、JWT 的结构

JWT 由三部分组成,用 . 分隔:

三、JWT 的验证过程

四、Token vs Session

对比 Session JWT Token
存储位置 服务器端 客户端
服务器状态 有状态(需要存 Session) 无状态(Token 自包含)
扩展性 多服务器需要共享 Session(Redis) 天然支持分布式
注销 删除服务器 Session 即可 需要额外机制(黑名单)
安全性 Session ID 泄露可冒充 Token 泄露也可冒充
数据量 Cookie 只传 ID,很小 Token 较大(每次都要传)

第四部分:JWT 实战

一、服务端签发 JWT(C 语言伪代码)

cpp 复制代码
// JWT 结构(简化)
typedef struct {
    char header[128];      // Base64 编码的 Header
    char payload[512];     // Base64 编码的 Payload
    char signature[256];   // 签名
} JWT;

// 签发 JWT
char* createToken(int userId, const char* username, const char* secret) {
    // 1. 构造 Header
    const char* header = "{\"alg\":\"HS256\",\"typ\":\"JWT\"}";
    char* header_b64 = base64_encode(header);
    
    // 2. 构造 Payload
    char payload[512];
    time_t now = time(NULL);
    sprintf(payload, "{\"userId\":%d,\"username\":\"%s\",\"iat\":%ld,\"exp\":%ld}",
            userId, username, now, now + 3600);  // 1 小时过期
    char* payload_b64 = base64_encode(payload);
    
    // 3. 计算签名
    char to_sign[1024];
    sprintf(to_sign, "%s.%s", header_b64, payload_b64);
    char* signature = hmac_sha256(to_sign, secret);
    char* signature_b64 = base64_encode(signature);
    
    // 4. 拼接完整 Token
    char* token = malloc(2048);
    sprintf(token, "%s.%s.%s", header_b64, payload_b64, signature_b64);
    
    return token;
}

二、前端使用 JWT

javascript 复制代码
// 登录成功后存储 Token
fetch('/api/login', {
    method: 'POST',
    body: JSON.stringify({ username: 'zhangsan', password: '123' })
})
.then(res => res.json())
.then(data => {
    localStorage.setItem('token', data.token);  // 存到本地
});

// 后续请求带上 Token
fetch('/api/profile', {
    headers: {
        'Authorization': 'Bearer ' + localStorage.getItem('token')
    }
});

三、Access Token + Refresh Token

第五部分:三种方案对比与选择

对比 Cookie Session JWT Token
谁保存 浏览器 服务器 浏览器
谁验证 服务器 服务器 服务器(密钥验证)
自动携带 ✅ 浏览器自动 ✅ Cookie 带 ID ❌ 代码手动加
跨域 受限(Domain) 受限 天然支持
移动端 不方便 不方便 友好
分布式 不方便 需要 Redis 天然支持
注销 删 Cookie 删 Session 需要额外处理
防 CSRF 需 SameSite 需 SameSite 不受 CSRF 影响

选择建议

场景 推荐
传统 Web 网站(前后端不分离) Session + Cookie
RESTful API JWT Token
移动 App JWT Token
微服务/分布式系统 JWT Token
需要立即注销 Session(或 Token + 黑名单)

第六部分:常见攻击与防范

第七部分:面试题

1. Q:Cookie、Session、Token 的区别?

A:Cookie 存储在浏览器端,浏览器自动携带;Session 存储在服务器端,Cookie 只存 session_id;Token 也存储在浏览器端,但代码手动携带。Session 适合传统 Web,Token 适合 API 和分布式系统。

2. Q:JWT 的 Payload 是加密的吗?

A:不是! 只是 Base64 编码,任何人都能解码。不要放密码等敏感信息。JWT 的防篡改靠的是 Signature 签名。

3. Q:Token 过期了怎么办?

A:用 Refresh Token 换取新的 Access Token。两个 Token 都过期才需要重新登录。

4. Q:Cookie 的 HttpOnly 和 Secure 有什么作用?

A:HttpOnly 禁止 JavaScript 读取 Cookie(防 XSS 窃取);Secure 要求 Cookie 只在 HTTPS 中传输(防中间人窃取)。

5. Q:CSRF 攻击是什么?怎么防?

A:攻击者诱导用户点击链接,利用用户已登录的身份发起恶意请求。防御方式:SameSite Cookie、CSRF Token、验证 Referer。JWT 方案天然不受 CSRF 影响(Token 不是浏览器自动携带的)。


总结

一、三种方案对比

方案 核心原理 最适合
Cookie 浏览器自动存储和携带的小数据 记住偏好、跟踪
Session 服务器存储状态,Cookie 只传 ID 传统 Web 登录
JWT Token 自包含加密令牌,客户端主动携带 API、移动端、分布式

二、一句话记忆

Cookie 存浏览器、自动带,Session 存服务器、Cookie 只带 ID,Token 自包含、手动带。Session 适合传统网站,Token 适合 API 和分布式。JWT 的 Payload 只编码不加密,防篡改靠签名。

相关推荐
liuhaoodng6262 分钟前
《网络IA项目:单臂路由(vlan间通讯)优化实战版》
运维·网络·网络协议
EasyCVR28 分钟前
视频汇聚/视频融合/视频分析EasyCVR平台的三个诊断按钮,到底该点哪一个?一文告诉你
网络·easycvr·国标gb28181
国科安芯32 分钟前
星上计算的第一道防线:低轨遥感卫星载荷处理链中的AS32S601型抗辐射MCU—— 面向高分辨率成像与在轨智能处理的场景化综述
大数据·网络·人工智能·单片机·算法·低轨卫星·抗辐射
ITxiaobing20231 小时前
海外广告投放:AdTech 场景下 IP 地址库选型思考
服务器·网络·tcp/ip
QZ166560951591 小时前
高效・AI 优化・多模态:知镜-数据安全检测工具政务数据安全管理方案
网络·安全·网络安全
国科安芯1 小时前
从点火到入轨的毫秒尺度:商业运载火箭飞行时序控制中的抗辐射MCU可靠性边界—— 面向短时高可靠任务的单粒子效应证据与架构分析
网络·人工智能·单片机·嵌入式硬件·架构·火箭·抗辐射
dog2502 小时前
长肥管道下的 CUBIC
网络
呉師傅2 小时前
Win7剪切文件变成复制文件如何修改【资源管理器异常类故障】
运维·网络·windows·电脑
honsor2 小时前
机房动环实战:H-THDRJ45 双网口温湿度变送器 Modbus RTU RS485 冗余组网方案
运维·服务器·网络
洋不写bug2 小时前
HTTP(一):Fiddler下载、抓包请求响应解析
网络协议·http·fiddler·网络通信·抓包·http请求和响应