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

引言

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

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

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

第一部分: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 只编码不加密,防篡改靠签名。

相关推荐
++==13 分钟前
RESTful详解:核心思想、框架、与HTTP的区别,API的设计风格
后端·http·restful
楷哥爱开发37 分钟前
TikTok Shop新加坡本土店入驻:如何选择新加坡本土住宅IP?
网络·网络协议·tcp/ip
网安蟹佬霸1 小时前
# 网络流量分析实战:从Wireshark到入侵检测系统构建(2026最新版,附完整流量分析链与IDS规则集)
网络·测试工具·安全·开源·wireshark·密码学·哈希算法
昌原的儿子LEO4 小时前
进程和线程(2)
linux·服务器·网络
Zzzzmo_4 小时前
【网络原理】TCP/IP协议02
网络·tcp/ip
DianSan_ERP4 小时前
WMS接入电商平台自动化履约实战:一张订单从平台到出库的接口时序设计
java·前端·网络·数据库·安全·架构·自动化
数据知道4 小时前
漏洞挖掘方法论:从 Fuzz 到 0day 的思维框架
网络·安全·web安全·网络安全
智购科技自动售货机工厂4 小时前
2026自动售货机语音支付模块集成:从声纹识别到支付闭环的工程实践~YH
大数据·服务器·网络·数据库·人工智能
zcmodeltech6 小时前
煤化工沙盘模型控制系统设计与实现:多工段协同联动方案
网络·人工智能·stm32·嵌入式硬件·制造·多分类
huashengzsj6 小时前
企业OV泛域名证书价格多少?2026年市场报价与选购指南
网络协议·http·https