您现在的位置是:网站首页 > Cookie与Session管理文章详情
Cookie与Session管理
陈川
【
Node.js
】
25361人已围观
3739字
Cookie与Session的基本概念
Cookie是服务器发送到用户浏览器并保存在本地的一小块数据,浏览器会在后续请求中自动携带这些数据。Session则是服务器端存储的用户会话信息,通常用于跟踪用户状态。两者经常配合使用,Cookie用于存储Session ID,而实际数据存储在服务器端。
// Express中设置Cookie的简单示例
app.get('/set-cookie', (req, res) => {
res.cookie('username', 'john_doe', { maxAge: 900000, httpOnly: true });
res.send('Cookie has been set');
});
Express中的Cookie管理
Express提供了cookie-parser
中间件来简化Cookie操作。安装后,可以通过req.cookies
访问客户端发送的Cookie,使用res.cookie()
设置新的Cookie。
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
app.use(cookieParser());
app.get('/', (req, res) => {
console.log(req.cookies); // 读取Cookie
res.cookie('lastVisit', new Date().toISOString()); // 设置Cookie
res.send('Cookie example');
});
Cookie的常用选项包括:
maxAge
: 设置过期时间(毫秒)expires
: 设置具体过期日期httpOnly
: 防止客户端JavaScript访问secure
: 仅通过HTTPS传输sameSite
: 防止CSRF攻击
Session管理实现方式
Express本身不直接支持Session,需要借助中间件如express-session
。Session数据可以存储在内存、数据库或专用存储系统中。
const session = require('express-session');
app.use(session({
secret: 'your_secret_key',
resave: false,
saveUninitialized: true,
cookie: { secure: false, maxAge: 60000 }
}));
app.get('/login', (req, res) => {
req.session.user = { id: 123, name: 'John' };
res.send('Logged in');
});
存储Session到数据库
对于生产环境,通常需要将Session数据持久化存储。connect-mongo
可以将Session存储到MongoDB。
const MongoStore = require('connect-mongo');
app.use(session({
store: MongoStore.create({ mongoUrl: 'mongodb://localhost/session_db' }),
secret: 'your_secret_key',
resave: false,
saveUninitialized: false
}));
Cookie与Session的安全考虑
安全是Cookie和Session管理的核心问题。常见安全措施包括:
- 使用
httpOnly
防止XSS攻击 - 生产环境启用
secure
标志 - 设置合理的
sameSite
策略 - 定期更换Session密钥
- 对敏感操作实施CSRF保护
// 安全Cookie设置示例
res.cookie('auth_token', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict',
maxAge: 24 * 60 * 60 * 1000 // 1天
});
性能优化策略
随着用户量增长,Session管理可能成为性能瓶颈。优化策略包括:
- 使用Redis等内存数据库存储Session
- 减少Session数据量
- 实现分布式Session管理
- 设置合理的Session过期时间
// 使用Redis存储Session
const RedisStore = require('connect-redis')(session);
const redisClient = require('redis').createClient();
app.use(session({
store: new RedisStore({ client: redisClient }),
secret: 'your_secret_key',
resave: false,
saveUninitialized: false
}));
实际应用场景示例
购物车是Cookie和Session的典型应用场景。用户未登录时使用Cookie存储购物车信息,登录后迁移到Session。
app.post('/add-to-cart', (req, res) => {
if (!req.session.cart) {
req.session.cart = [];
}
const product = {
id: req.body.productId,
name: req.body.productName,
quantity: req.body.quantity || 1
};
req.session.cart.push(product);
res.json({ success: true, cart: req.session.cart });
});
常见问题与解决方案
- Session丢失问题:确保Session存储配置正确,检查中间件顺序
- Cookie不被保存:检查域名、路径和安全设置
- 跨域Session共享:配置相同的Session密钥和Cookie域
- 内存泄漏:避免使用默认的内存存储在生产环境
// 解决跨子域Session共享
app.use(session({
secret: 'your_secret_key',
cookie: {
domain: '.example.com',
maxAge: 24 * 60 * 60 * 1000
}
}));
高级主题:JWT替代方案
JSON Web Token(JWT)是另一种身份验证机制,适合无状态API。与Session相比各有优缺点。
const jwt = require('jsonwebtoken');
// 生成JWT
app.post('/login', (req, res) => {
const token = jwt.sign({ userId: 123 }, 'secret_key', { expiresIn: '1h' });
res.cookie('jwt', token, { httpOnly: true });
res.json({ token });
});
// 验证JWT
app.get('/profile', (req, res) => {
const token = req.cookies.jwt;
try {
const decoded = jwt.verify(token, 'secret_key');
res.json(decoded);
} catch (err) {
res.status(401).send('Invalid token');
}
});