在 Web 应用中,HTTP 协议本身是无状态的。服务器无法仅凭一次请求就判断"当前用户是谁、之前做过什么操作"。为了解决状态保持的问题,Cookie 与 Session 成为了 Web 开发中最基础、也最重要的机制之一。本文将结合 Node.js,系统讲解 Cookie 与 Session 的工作原理、使用方式以及常见实践。
一、为什么需要 Cookie 与 Session
HTTP 是一种无状态协议,每一次请求都是独立的:
- 服务器不会记住上一次请求的用户
- 不同请求之间默认没有任何关联
- 用户登录状态无法自动保持
如果没有状态机制,就无法实现登录、购物车、个性化配置等功能。Cookie 与 Session 的出现,正是为了在"无状态协议"之上,构建"有状态的应用体验"。
二、Cookie 的基本概念
Cookie 是服务器发送给浏览器的一小段数据,浏览器会将其保存在本地,并在后续请求中自动携带回服务器。
Cookie 的特点包括:
- 存储在客户端(浏览器)
- 每次请求都会随 HTTP 头一起发送
- 大小有限(通常不超过 4KB)
- 可以设置过期时间、作用域和安全属性
从本质上看,Cookie 是服务器在客户端保存状态信息的一种方式。
三、Node.js 中操作 Cookie
1. 设置 Cookie
在 Node.js 原生 http 模块中,可以通过响应头设置 Cookie。
js
const http = require("http");
const server = http.createServer((req, res) => {
res.setHeader("Set-Cookie", "username=nodejs; Max-Age=3600");
res.end("Cookie set");
});
server.listen(3000);
上面的代码会在浏览器中保存一个名为 username 的 Cookie,有效期为一小时。
2. 读取 Cookie
浏览器发送的 Cookie 会出现在请求头中。
js
const cookie = req.headers.cookie;
console.log(cookie);
如果有多个 Cookie,它们会以分号分隔的形式出现,需要手动解析。
js
function parseCookie(cookieStr = "") {
const cookies = {};
cookieStr.split(";").forEach(item => {
const [key, value] = item.split("=");
if (key && value) {
cookies[key.trim()] = value.trim();
}
});
return cookies;
}
四、Cookie 的常见属性
Cookie 并不仅仅是键值对,还可以设置多种属性来增强安全性和控制范围。
Max-Age / Expires:控制 Cookie 过期时间Path:限制 Cookie 生效的路径Domain:限制 Cookie 生效的域名HttpOnly:禁止 JavaScript 访问 CookieSecure:仅在 HTTPS 连接下发送
合理设置这些属性,是 Web 安全的重要一环。
五、Session 的核心思想
Session 是服务器端保存用户状态的一种机制。 与 Cookie 不同,Session 的核心数据存储在服务器中。
常见的工作流程是:
- 用户第一次访问服务器
- 服务器创建一个 Session,并生成 Session ID
- 服务器将 Session ID 通过 Cookie 发送给客户端
- 客户端后续请求携带该 Session ID
- 服务器根据 Session ID 查找对应的 Session 数据
Session 解决了 Cookie 数据暴露在客户端的问题。
六、Node.js 中的简单 Session 实现
下面是一个基于内存的简易 Session 示例,用于理解原理。
js
const http = require("http");
const crypto = require("crypto");
const sessions = {};
function generateSessionId() {
return crypto.randomBytes(16).toString("hex");
}
const server = http.createServer((req, res) => {
let sid;
const cookies = parseCookie(req.headers.cookie);
sid = cookies.sid;
if (!sid || !sessions[sid]) {
sid = generateSessionId();
sessions[sid] = { count: 0 };
res.setHeader("Set-Cookie", `sid=${sid}; HttpOnly`);
}
sessions[sid].count++;
res.end(`Visit count: ${sessions[sid].count}`);
});
server.listen(3000);
这个例子展示了 Session 的基本流程,但并不适合生产环境。
七、Cookie 与 Session 的区别
从设计角度来看,两者的差异非常明显:
- Cookie 存储在客户端,Session 存储在服务器
- Cookie 容量小,Session 理论上更灵活
- Cookie 更容易被篡改,Session 相对安全
- Session 通常依赖 Cookie 传递 Session ID
在实际开发中,它们往往是配合使用的,而不是二选一。
八、生产环境中的 Session 管理
在真实项目中,Session 通常不会存储在内存中,而是使用:
- Redis
- 数据库
- 分布式缓存系统
这样可以支持:
- 服务重启不丢失 Session
- 多实例部署下的 Session 共享
- 更好的性能与扩展性
在 Node.js 项目中,Express 通常会搭配 express-session 与 Redis 一起使用。
九、Cookie 与 Session 的安全实践
在涉及登录和用户身份的场景中,安全尤为重要:
- Session ID 必须足够随机,防止猜测
- Cookie 应设置
HttpOnly,防止 XSS - 使用 HTTPS 并开启
Secure属性 - 定期清理过期 Session
- 避免在 Cookie 中存储敏感信息
这些细节直接决定了系统的安全等级。
十、总结
通过本文,你应该已经掌握:
- Cookie 与 Session 出现的背景
- Cookie 的基本原理与 Node.js 实现方式
- Session 的核心思想与运行流程
- 两者的差异与使用场景
- 实际项目中的安全与架构建议
Cookie 与 Session 是 Node.js Web 开发中绕不开的基础知识。理解它们的原理,比单纯会用框架更重要,也为后续学习认证系统、权限控制和分布式架构打下坚实基础。