乐闻世界logo
搜索文章和话题

Koa 中 Cookie 和 Session 管理的实现方法

2月21日 15:53

Koa 的 Cookie 和 Session 管理是构建 Web 应用的基础功能,Koa 核心提供了 Cookie 操作,而 Session 需要通过中间件实现。

1. Cookie 操作:

Koa 核心内置了 Cookie 功能,通过 ctx.cookies 对象进行操作。

设置 Cookie:

javascript
app.use(async (ctx) => { // 基本设置 ctx.cookies.set('name', 'value'); // 带选项的设置 ctx.cookies.set('username', 'john', { maxAge: 3600000, // 有效期(毫秒) expires: new Date('2025-12-31'), // 过期时间 path: '/', // 路径 domain: '.example.com', // 域名 secure: true, // 仅 HTTPS httpOnly: true, // 仅 HTTP,防止 XSS sameSite: 'strict', // CSRF 保护 signed: true // 签名 Cookie }); ctx.body = 'Cookie set'; });

获取 Cookie:

javascript
app.use(async (ctx) => { const username = ctx.cookies.get('username'); ctx.body = `Hello ${username}`; });

删除 Cookie:

javascript
app.use(async (ctx) => { ctx.cookies.set('username', null, { maxAge: 0, path: '/' }); ctx.body = 'Cookie deleted'; });

2. Session 管理:

使用 koa-session 中间件实现 Session 功能。

安装:

bash
npm install koa-session

基本配置:

javascript
const session = require('koa-session'); const sessionConfig = { key: 'koa.sess', // Cookie 名称 maxAge: 86400000, // 有效期(毫秒) autoCommit: true, // 自动提交 overwrite: true, // 覆盖 httpOnly: true, // 仅 HTTP signed: true, // 签名 rolling: false, // 每次请求更新过期时间 renew: false, // 快过期时自动续期 secure: false, // 仅 HTTPS sameSite: null, // SameSite 策略 }; app.keys = ['your-secret-key']; // 必须设置用于签名 app.use(session(sessionConfig, app));

Session 使用:

javascript
// 设置 Session app.use(async (ctx) => { if (ctx.path === '/login') { ctx.session.user = { id: 1, name: 'John', role: 'admin' }; ctx.body = 'Logged in'; } }); // 获取 Session app.use(async (ctx) => { if (ctx.path === '/profile') { const user = ctx.session.user; if (user) { ctx.body = `Welcome ${user.name}`; } else { ctx.throw(401, 'Not logged in'); } } }); // 删除 Session app.use(async (ctx) => { if (ctx.path === '/logout') { ctx.session = null; ctx.body = 'Logged out'; } });

3. Redis Session 存储:

对于生产环境,建议使用 Redis 存储 Session。

安装:

bash
npm install koa-session koa-redis

配置 Redis Session:

javascript
const session = require('koa-session'); const RedisStore = require('koa-redis'); const redisStore = RedisStore({ host: 'localhost', port: 6379, password: 'your-password', db: 0 }); const sessionConfig = { store: redisStore, key: 'koa.sess', maxAge: 86400000, httpOnly: true, signed: true }; app.keys = ['your-secret-key']; app.use(session(sessionConfig, app));

4. 认证中间件示例:

javascript
// 认证中间件 async function authMiddleware(ctx, next) { if (!ctx.session.user) { ctx.throw(401, 'Unauthorized'); } await next(); } // 使用认证中间件 router.get('/protected', authMiddleware, async (ctx) => { ctx.body = `Welcome ${ctx.session.user.name}`; });

5. JWT Token 认证:

使用 jsonwebtokenkoa-jwt 实现 JWT 认证。

安装:

bash
npm install jsonwebtoken koa-jwt

生成 Token:

javascript
const jwt = require('jsonwebtoken'); app.use(async (ctx) => { if (ctx.path === '/login') { const { username, password } = ctx.request.body; // 验证用户 const user = await authenticateUser(username, password); // 生成 Token const token = jwt.sign( { id: user.id, name: user.name }, 'your-secret-key', { expiresIn: '24h' } ); ctx.body = { token }; } });

验证 Token:

javascript
const jwt = require('koa-jwt'); app.use(jwt({ secret: 'your-secret-key' }).unless({ path: [/^\/public/, '/login', '/register'] })); // 访问用户信息 app.use(async (ctx) => { ctx.body = ctx.state.user; });

6. 完整的认证流程示例:

javascript
const Koa = require('koa'); const Router = require('@koa/router'); const session = require('koa-session'); const jwt = require('jsonwebtoken'); const koaJwt = require('koa-jwt'); const app = new Koa(); const router = new Router(); // Session 配置 app.keys = ['secret-key']; app.use(session({ key: 'koa.sess', maxAge: 86400000 }, app)); // JWT 中间件 app.use(koaJwt({ secret: 'jwt-secret' }).unless({ path: [/^\/api\/auth/] })); // 登录路由 router.post('/api/auth/login', async (ctx) => { const { username, password } = ctx.request.body; // 验证用户 const user = await User.findOne({ username }); if (!user || !await user.comparePassword(password)) { ctx.throw(401, 'Invalid credentials'); } // 设置 Session ctx.session.user = { id: user.id, name: user.name }; // 生成 JWT Token const token = jwt.sign( { id: user.id, name: user.name }, 'jwt-secret', { expiresIn: '24h' } ); ctx.body = { token, user: { id: user.id, name: user.name } }; }); // 受保护的路由 router.get('/api/user/profile', async (ctx) => { ctx.body = ctx.state.user; }); // 登出路由 router.post('/api/auth/logout', async (ctx) => { ctx.session = null; ctx.body = { message: 'Logged out' }; }); app.use(router.routes());

7. 安全最佳实践:

  1. Cookie 安全:

    • 始终设置 httpOnly: true 防止 XSS
    • 生产环境使用 secure: true 仅 HTTPS
    • 设置 sameSite: 'strict' 防止 CSRF
    • 使用签名 Cookie 防止篡改
  2. Session 安全:

    • 使用强随机密钥
    • 设置合理的过期时间
    • 生产环境使用 Redis 存储
    • 登出时清除 Session
  3. JWT 安全:

    • 使用强密钥
    • 设置合理的过期时间
    • 使用 HTTPS 传输
    • 实现 Token 刷新机制
  4. 其他安全措施:

    • 限制登录尝试次数
    • 实现密码强度验证
    • 记录认证日志
    • 定期更新密钥
标签:Koa