Cookie operations and security settings
Basic Concepts of Cookies
Cookies are small pieces of data sent from a server to a 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. Cookies are primarily used for session state management, personalized settings, and behavior tracking. In Koa2, cookie operations are typically implemented through the ctx.cookies
interface.
// Set a simple cookie
ctx.cookies.set('username', 'JohnDoe', {
httpOnly: true,
maxAge: 24 * 60 * 60 * 1000 // 1 day
});
Cookie Operations in Koa2
Koa2 provides the ctx.cookies
object for convenient cookie operations. This object offers get
and set
methods for reading and setting cookies, respectively.
Setting Cookies
Multiple options can be specified when setting a cookie:
ctx.cookies.set('token', 'abc123', {
domain: '.example.com', // Accessible domain
path: '/admin', // Accessible path
maxAge: 86400000, // Validity period (milliseconds)
expires: new Date('2023-12-31'), // Expiration time
httpOnly: true, // HTTP-only access
secure: true, // HTTPS-only transmission
sameSite: 'strict' // Same-site policy
});
Reading Cookies
Reading cookies is straightforward:
const username = ctx.cookies.get('username');
console.log(username); // Output: JohnDoe
Deleting Cookies
Deleting a cookie is achieved by setting its expiration time to a past date:
ctx.cookies.set('username', null, {
maxAge: -1
});
Cookie Security Settings
Cookie security settings are crucial for preventing cross-site scripting (XSS) and cross-site request forgery (CSRF) attacks.
HttpOnly Flag
ctx.cookies.set('sessionId', 's3cr3t', {
httpOnly: true // Prevents JavaScript access
});
Secure Flag
ctx.cookies.set('auth', 'token123', {
secure: true // Transmitted only over HTTPS
});
SameSite Attribute
The SameSite attribute helps prevent CSRF attacks:
ctx.cookies.set('csrftoken', 'randomvalue', {
sameSite: 'strict' // or 'lax'
});
Cookie Signing
Koa2 supports signing cookies to prevent client-side tampering:
// Set the signing key during app initialization
app.keys = ['my secret key'];
// Set a signed cookie
ctx.cookies.set('cart', JSON.stringify(items), {
signed: true
});
// Read a signed cookie
const cart = ctx.cookies.get('cart', { signed: true });
Cookies and Sessions
In Koa2, cookies are often used to implement sessions:
const sessionId = ctx.cookies.get('sessionId', { signed: true });
if (!sessionId) {
const newSessionId = generateSessionId();
ctx.cookies.set('sessionId', newSessionId, {
signed: true,
httpOnly: true
});
// Initialize session data
}
Common Issues and Solutions
Cookie Size Limit
A single cookie should generally not exceed 4KB. For large amounts of data, consider:
// Store data on the server and pass only an identifier via cookie
ctx.cookies.set('dataRef', 'unique-id', {
httpOnly: true
});
// Store the actual data on the server
dataStore.set('unique-id', largeData);
Sharing Cookies Across Multiple Domains
ctx.cookies.set('shared', 'value', {
domain: '.example.com' // Shared across all subdomains
});
Browser Compatibility
For older browsers that don't support SameSite, additional measures are needed:
// Set dual cookies
ctx.cookies.set('legacy_session', 'value', {
secure: true,
httpOnly: true
});
ctx.cookies.set('__Secure-session', 'value', {
secure: true,
httpOnly: true,
sameSite: 'none'
});
Performance Optimization
Reducing Cookie Quantity
Merge multiple small cookies:
// Not recommended
ctx.cookies.set('pref1', 'value1');
ctx.cookies.set('pref2', 'value2');
// Recommended
const preferences = {
pref1: 'value1',
pref2: 'value2'
};
ctx.cookies.set('preferences', JSON.stringify(preferences));
Separating Static Resource Domains
Use cookie-free domains for static resources:
<!-- Main site -->
<script src="https://www.example.com/app.js"></script>
<!-- Static resources use a separate domain -->
<img src="https://static.example.com/image.jpg">
Practical Application Examples
Shopping Cart Implementation
// Add item to cart
router.post('/cart/add', async (ctx) => {
const { productId, quantity } = ctx.request.body;
let cart = JSON.parse(ctx.cookies.get('cart') || {};
cart[productId] = (cart[productId] || 0) + quantity;
ctx.cookies.set('cart', JSON.stringify(cart), {
maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days
httpOnly: true,
signed: true
});
ctx.body = { success: true };
});
User Preference Settings
// Save user theme preference
router.post('/preferences/theme', async (ctx) => {
const { theme } = ctx.request.body;
ctx.cookies.set('userPrefs', JSON.stringify({
...JSON.parse(ctx.cookies.get('userPrefs') || '{}'),
theme
}), {
maxAge: 365 * 24 * 60 * 60 * 1000, // 1 year
httpOnly: true
});
ctx.body = { success: true };
});
Security Best Practices
- Always set HttpOnly and Secure flags for sensitive cookies.
- Use signed cookies for important data.
- Configure the SameSite attribute appropriately.
- Avoid storing sensitive information in cookies.
- Rotate signing keys periodically.
- Set reasonable expiration times.
// Secure cookie example
ctx.cookies.set('authToken', generateToken(), {
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: 3600000, // 1 hour
signed: true
});
Debugging and Testing
Viewing Cookies
Cookies can be viewed and modified in the Application panel of Chrome Developer Tools.
Unit Test Example
const request = require('supertest');
const app = require('../app');
describe('Cookie Test', () => {
it('should set cookie', async () => {
const res = await request(app)
.get('/set-cookie')
.expect(200);
expect(res.headers['set-cookie']).toBeDefined();
});
});
Integration with Other Technologies
Integration with JWT
// Set JWT as HttpOnly cookie
ctx.cookies.set('jwt', generateJWT(user), {
httpOnly: true,
secure: true,
maxAge: 3600000
});
// Verify in middleware
const jwtMiddleware = async (ctx, next) => {
const token = ctx.cookies.get('jwt');
if (!token) {
ctx.throw(401, 'Unauthorized');
}
try {
ctx.state.user = verifyJWT(token);
await next();
} catch (err) {
ctx.throw(401, 'Invalid token');
}
};
Integration with CSRF Protection
// Generate CSRF token
const csrf = require('koa-csrf');
app.use(csrf());
// Include CSRF token in forms
router.get('/form', async (ctx) => {
ctx.body = `
<form action="/submit" method="POST">
<input type="hidden" name="_csrf" value="${ctx.csrf}">
<!-- Other form fields -->
</form>
`;
});
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:多种内容类型的响应处理
下一篇:Session 管理的实现方案