Cookie and Session Management
Basic Concepts of Cookies and Sessions
Cookies are small pieces of data sent from the server to the user's browser and stored locally. They are carried and sent back to the server when the browser makes subsequent requests to the same server. Sessions, on the other hand, are a server-side mechanism for storing user session information, typically implemented using cookies.
// Setting a simple cookie
res.cookie('username', 'john_doe', { maxAge: 900000, httpOnly: true });
Cookie Management in Express
Express simplifies cookie operations using the cookie-parser
middleware. First, install and import the middleware:
npm install cookie-parser
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
app.use(cookieParser());
Multiple options can be specified when setting cookies:
res.cookie('token', 'abc123xyz', {
maxAge: 24 * 60 * 60 * 1000, // 1 day
secure: true, // HTTPS only
httpOnly: true, // Prevents XSS
sameSite: 'strict' // CSRF protection
});
Reading cookies is straightforward:
app.get('/', (req, res) => {
const userToken = req.cookies.token;
// Use the token for authentication
});
To delete a cookie:
res.clearCookie('token');
Session Management Implementation
Express does not natively support sessions; middleware is required. Common solutions include:
- In-Memory Session (for development)
const session = require('express-session');
app.use(session({
secret: 'your_secret_key',
resave: false,
saveUninitialized: true
}));
- Redis Session Storage (recommended for production)
const redis = require('redis');
const RedisStore = require('connect-redis')(session);
const redisClient = redis.createClient();
app.use(session({
store: new RedisStore({ client: redisClient }),
secret: 'your_secret_key',
resave: false,
saveUninitialized: false,
cookie: { secure: true }
}));
Typical Use Cases for Sessions
Maintaining user login status:
// Set session on login
app.post('/login', (req, res) => {
const { username, password } = req.body;
// Authentication logic...
req.session.user = {
id: user.id,
username: user.username,
role: user.role
};
res.redirect('/dashboard');
});
// Authentication middleware
function checkAuth(req, res, next) {
if (!req.session.user) {
return res.status(401).send('Please log in first');
}
next();
}
// Protected route
app.get('/profile', checkAuth, (req, res) => {
res.render('profile', { user: req.session.user });
});
Shopping cart implementation example:
// Add item to cart
app.post('/cart/add', (req, res) => {
if (!req.session.cart) {
req.session.cart = [];
}
req.session.cart.push(req.body.product);
res.json({ success: true });
});
// Retrieve cart contents
app.get('/cart', (req, res) => {
res.json(req.session.cart || []);
});
Security Best Practices
- Cookie Security Settings
app.use(session({
// ...
cookie: {
secure: process.env.NODE_ENV === 'production',
httpOnly: true,
sameSite: 'lax',
maxAge: 24 * 60 * 60 * 1000
}
}));
- Preventing Session Fixation Attacks
app.use(session({
// ...
genid: (req) => {
return crypto.randomUUID(); // Use strong random IDs
}
}));
- Regularly Rotate Session Secrets
app.use(session({
secret: [currentSecret, oldSecret],
rolling: true // Refresh expiration on each request
}));
Performance Optimization Tips
- Session Storage Optimization
app.use(session({
// ...
saveUninitialized: false, // Do not save unmodified sessions
resave: false, // Avoid unnecessary rewrites
cookie: {
maxAge: 30 * 60 * 1000 // Expire after 30 minutes of inactivity
}
}));
- Distributed Session Management
// Using MongoDB for session storage
const MongoStore = require('connect-mongo');
app.use(session({
store: MongoStore.create({
mongoUrl: 'mongodb://localhost/session_db',
ttl: 14 * 24 * 60 * 60 // 14 days
}),
// ...
}));
- Reduce Session Data Size
// Store only essential information
req.session.user = {
id: user.id, // Store only ID; fetch other data from DB
lastActive: Date.now()
};
Common Issue Solutions
- Cookie Size Limitations
// For large data, use database references
req.session.largeDataRef = 'data_id';
// Store actual data in the database
- Cross-Domain Session Sharing
app.use(session({
// ...
cookie: {
domain: '.example.com', // Allow subdomain sharing
path: '/'
}
}));
- Mobile Session Handling
// For API requests, use tokens instead of cookies
app.post('/api/login', (req, res) => {
// On successful authentication
const token = generateToken(user);
res.json({ token });
// Or use cookies with mobile-friendly settings
res.cookie('session', token, {
httpOnly: true,
sameSite: 'none',
secure: true
});
});
Advanced Use Cases
- Multi-Device Session Management
// Store device info in session
req.session.devices = req.session.devices || [];
req.session.devices.push({
id: deviceId,
ip: req.ip,
userAgent: req.headers['user-agent'],
lastActive: new Date()
});
// Implement device management
app.get('/account/devices', (req, res) => {
res.render('devices', { devices: req.session.devices });
});
app.post('/account/devices/revoke', (req, res) => {
req.session.devices = req.session.devices.filter(
d => d.id !== req.body.deviceId
);
res.redirect('/account/devices');
});
- Real-Time Permission Changes
// When admin updates user permissions
function updateUserPermissions(userId, newRole) {
// Update database
// Then update all active sessions
sessionStore.all((err, sessions) => {
for (const sessionId in sessions) {
if (sessions[sessionId].user.id === userId) {
sessions[sessionId].user.role = newRole;
sessionStore.set(sessionId, sessions[sessionId]);
}
}
});
}
- Combining Long-Term and Short-Term Sessions
// Regular session (short-term)
app.use(session({
name: 'session',
secret: 'short_term_secret',
cookie: { maxAge: 30 * 60 * 1000 } // 30 minutes
}));
// "Remember Me" feature (long-term)
app.post('/login', (req, res) => {
// Authentication logic...
if (req.body.rememberMe) {
const longTermToken = generateToken();
res.cookie('remember_me', longTermToken, {
maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days
httpOnly: true,
secure: true
});
// Store token in DB linked to user
}
});
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn