Http的请求与响应 Cookie和Session的用法
Cookie是浏览器端的存储与自动发送机制,用来携带凭证。Session是服务器端的数据档案,通过 Session ID 关联。两者配合,解决了 HTTP 无状态的问题。HttpOnlySecureSameSite、HTTPS、输入校验缺一不可。随着架构演进,JWT 等无状态 Token 方案在分布式和跨端场景中逐渐成为主角。记住:没有万能的方案,只有适合当前场景的权衡。下次当你点击“记住我”或打
你是否好奇过:为什么网站能记住你的登录状态?为什么购物车里的商品换个页面还在?这背后离不开两个核心角色——Cookie 和 Session。它们共同撑起了 Web 应用的状态管理,让无状态的 HTTP 协议拥有了“记忆”。今天,我们不仅会讲清楚它们的原理,还会聊聊安全、性能以及现代 Web 中的替代方案。
1. 为什么需要 Cookie 和 Session?
HTTP 协议本身是无状态的。这意味着每个请求都是独立的,服务器收到一个请求时,并不天然知道这个请求和之前的请求是否来自同一个用户。
想象一下:你登录了网银,查询余额时服务器却问“你是谁”;把商品加入购物车,结算时购物车却空空如也——这显然不可接受。
为了让服务器能“认出”同一个用户,Cookie 和 Session 应运而生。
2. Cookie:客户端的身份凭证
Cookie 是服务器发送给浏览器的一小段文本数据(通常不超过 4KB)。浏览器会将其存储下来,并在后续的每次请求中,自动将同名的 Cookie 带回到服务器。
2.1 Cookie 的典型工作流程
-
用户首次访问网站,浏览器发起请求。
-
服务器在响应头中添加
Set-Cookie指令,例如:text
Set-Cookie: sessionId=abc123; Path=/; HttpOnly; Secure; SameSite=Lax
-
浏览器收到后,解析并保存这个 Cookie。
-
之后对同一域名的每次请求,浏览器都会自动在请求头中加入:
text
Cookie: sessionId=abc123
-
服务器读取这个 Cookie,识别用户身份。
2.2 Cookie 的关键属性
| 属性 | 作用 | 重要性 |
|---|---|---|
Name=Value |
核心数据,键值对形式 | 必选 |
Domain / Path |
控制 Cookie 的生效范围 | 安全隔离 |
Expires / Max-Age |
持久化 Cookie 的有效期 | 会话 Cookie 若不设置,浏览器关闭即失效 |
HttpOnly |
禁止 JavaScript 访问,有效防御 XSS 攻击 | ⭐ 安全必设 |
Secure |
仅通过 HTTPS 传输 | ⭐ 安全必设 |
SameSite |
控制跨站请求是否携带 Cookie,防御 CSRF | ⭐ 重要(Lax 或 Strict) |
2.3 Cookie 的两类形态
-
会话级 Cookie:不设置
Expires或Max-Age,存储在内存中,浏览器关闭即消失。 -
持久化 Cookie:设置了过期时间,存储在硬盘上,到期前一直有效(即使用户重启电脑)。
3. Session:服务端的私密档案夹
如果说 Cookie 是把“身份牌”发给用户保管,那么 Session 就是服务器端的一本花名册。Session 数据存储在服务器上,客户端只保存一个唯一标识 —— Session ID(通常通过 Cookie 传递)。
3.1 Session 的工作流程
-
用户首次访问,服务器创建一个 Session 对象,生成唯一的 Session ID。
-
服务器通过
Set-Cookie将Session ID发送给浏览器(通常命名为JSESSIONID、sid等)。 -
浏览器后续请求自动带上这个
Session ID。 -
服务器根据
Session ID查找对应的 Session 数据,从而获取用户的登录信息、购物车等状态。
3.2 Session 的存储方式
Session 数据可以存放在:
-
内存(默认开发场景,生产环境不要用,重启丢失且无法共享)
-
数据库(MySQL、PostgreSQL)
-
缓存(Redis、Memcached)—— 生产环境首选
3.3 为什么 Session 比 Cookie 更安全?
敏感数据不经过客户端。如果直接把用户 ID、权限等级存在 Cookie 里,任何人都可以篡改(例如把 role=user 改成 role=admin)。而 Session 只把不可猜测的随机 ID 给客户端,真实数据躺在受服务器保护的存储中,无法被用户直接篡改。
4. 一张表看懂 Cookie 与 Session 的核心区别
| 维度 | Cookie | Session |
|---|---|---|
| 存储位置 | 浏览器端 | 服务器端 |
| 容量限制 | 约 4KB | 无硬性限制(受服务器内存/存储限制) |
| 安全性 | 较低(数据可见,可篡改,需加密签名) | 较高(ID 不可猜测,真实数据不暴露) |
| 性能 | 无服务器存储压力 | 大量 Session 会占用服务器资源 |
| 跨域支持 | 需特殊配置,默认同源 | 依赖 Session ID 的传递方式 |
| 移动端适用性 | 依赖 Cookie 机制,部分 App 需手动处理 | 可用 Token 替代 |
5. 实战:Node.js + Express 演示登录与状态保持
下面我们用一个极简的例子来串联整个过程。
javascript
// 安装依赖:npm install express express-session cookie-parser
const express = require('express');
const session = require('express-session');
const app = express();
// 配置 Session 中间件
app.use(session({
secret: 'your-secret-key', // 用于签名 Session ID
resave: false,
saveUninitialized: true,
cookie: {
httpOnly: true,
secure: false, // 生产环境必须 true (HTTPS)
maxAge: 1000 * 60 * 30 // 30 分钟
}
}));
// 登录接口(模拟)
app.post('/login', (req, res) => {
// 假设验证用户名密码成功
req.session.user = { id: 1, name: 'Alice' };
req.session.loggedIn = true;
res.send('登录成功,Session 已建立');
});
// 需要登录的接口
app.get('/profile', (req, res) => {
if (req.session.loggedIn) {
res.json(req.session.user);
} else {
res.status(401).send('请先登录');
}
});
// 退出登录
app.post('/logout', (req, res) => {
req.session.destroy(err => {
if (err) return res.status(500).send('退出失败');
res.clearCookie('connect.sid'); // 清除 Session Cookie
res.send('已退出');
});
});
app.listen(3000);
验证步骤:
-
使用
curl或浏览器先调用/login,注意响应头中的Set-Cookie。 -
调用
/profile时带上 Cookie 头,就能获取用户信息。 -
调用
/logout后,再访问/profile会返回 401。
6. 安全隐患与最佳防御
Cookie + Session 虽然经典,但并非银弹。以下是三大典型攻击及对策。
6.1 XSS(跨站脚本攻击)
攻击者注入恶意脚本,读取 document.cookie 盗取 Session ID。
防御:
-
设置
HttpOnly,禁止 JS 读取 Cookie。 -
对用户输入进行严格的过滤/转义。
-
使用 CSP(内容安全策略)。
6.2 CSRF(跨站请求伪造)
攻击者诱导用户点击恶意链接,利用浏览器自动携带 Cookie 的机制,以用户身份发送伪造请求。
防御:
-
关键操作使用
SameSite=Lax或Strict。 -
使用 CSRF Token(服务端下发随机 token,提交时验证)。
-
验证
Referer/Origin头。
6.3 Session 劫持
攻击者通过网络嗅探或 XSS 窃取 Session ID。
防御:
-
强制 HTTPS +
Secure标记。 -
定期轮换 Session ID(登录后、权限变更后调用
req.session.regenerate())。 -
绑定客户端特征(如 IP 段、User-Agent 哈希)。
7. 现代 Web 的演进:Token 与 JWT
分布式微服务和移动端普及后,传统 Session 暴露出一些短板:
-
服务器必须集中存储 Session(Redis 可解,但增加架构复杂度)。
-
无法轻松跨域或跨服务共享。
-
移动端 App 处理 Cookie 不如浏览器那么自动。
于是 Token(令牌) 方案流行起来,尤其是 JWT(JSON Web Token)。
JWT 的特点
-
自包含:用户信息(如 userId、role)直接编码在 Token 中,服务器无需存储。
-
客户端存储(通常放在 localStorage 或内存,通过 Authorization 头发送)。
-
签名防篡改(服务器用密钥验证)。
javascript
// JWT 示例载荷
{
"sub": "1234567890",
"name": "Alice",
"iat": 1516239022,
"exp": 1516242622
}
优缺点对比:
-
✅ 无状态,适合分布式系统。
-
✅ 跨语言、跨平台友好。
-
❌ 一旦签发,无法主动撤销(除非加黑名单,又变回了有状态)。
-
❌ 载荷体积比 Cookie 大(每次请求都带着)。
最佳实践:取长补短
-
传统单体应用:Session + Cookie(简单、安全、可控)。
-
REST API / SPA / 移动端:JWT + 刷新令牌 (Refresh Token)。
-
高安全场景(银行、政务):双重验证 + 短生命周期 Token + 实时撤销能力。
8. 总结
-
Cookie 是浏览器端的存储与自动发送机制,用来携带凭证。
-
Session 是服务器端的数据档案,通过 Session ID 关联。
-
两者配合,解决了 HTTP 无状态的问题。
-
安全永远是第一优先级:
HttpOnly、Secure、SameSite、HTTPS、输入校验缺一不可。 -
随着架构演进,JWT 等无状态 Token 方案在分布式和跨端场景中逐渐成为主角。
记住:没有万能的方案,只有适合当前场景的权衡。下次当你点击“记住我”或打开购物车时,你应该能清晰看到 Cookie 和 Session 在幕后默默协作的身影。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)