如何通过koa-generic-session将第三方API的JWT Token存入HttpOnly Cookie?
我之前刚好做过类似的需求,用koa-generic-session把JWT存到HttpOnly Cookie里其实挺顺手的,给你一步步说清楚怎么做:
步骤1:安装必要依赖
首先得装koa-generic-session,如果你还没装koa、请求工具或JWT验证库的话也一起装上:
npm install koa koa-generic-session axios jsonwebtoken
(axios用来调用第三方API拿JWT,jsonwebtoken用来后续验证JWT,可根据你的实际需求调整)
步骤2:配置koa-generic-session中间件
在你的koa入口文件(比如app.js)里,先设置签名密钥,再挂载session中间件:
const Koa = require('koa'); const session = require('koa-generic-session'); const app = new Koa(); // 重要:设置Cookie签名密钥,一定要用安全的、唯一的密钥,建议用环境变量存储 app.keys = [process.env.SESSION_SECRET || 'your-strong-and-unique-secret-key']; // 配置session中间件,核心是开启HttpOnly和签名 app.use(session({ key: 'jwtToken', // Cookie的键名,你可以自定义 httpOnly: true, // 强制开启HttpOnly,避免XSS攻击窃取Cookie signed: true, // 开启Cookie签名,防止Cookie被篡改 maxAge: 3600 * 1000, // Cookie过期时间,要和第三方JWT的expiresIn保持一致(这里是1小时) rolling: false, // 是否每次请求都刷新Cookie过期时间,按需设置 overwrite: true // 允许覆盖已有session值 })); // 挂载路由(后面会写路由逻辑) app.use(require('./routes').routes()); app.listen(3000, () => { console.log('Server running on port 3000'); });
在你的路由文件里,写一个登录接口,调用第三方API拿到JWT后,直接赋值给ctx.session.jwt,koa-generic-session会自动帮你把这个值写入HttpOnly Cookie:
const Router = require('koa-router'); const axios = require('axios'); const router = new Router(); router.post('/login', async (ctx) => { try { // 调用第三方API获取JWT,这里替换成你的第三方接口地址和参数 const thirdPartyResponse = await axios.post('https://第三方登录API地址', { username: ctx.request.body.username, password: ctx.request.body.password }); const jwtToken = thirdPartyResponse.data.token; // 把JWT存入session,koa-generic-session会自动写入HttpOnly Cookie ctx.session.jwt = jwtToken; ctx.body = { success: true, message: '登录成功' }; } catch (error) { ctx.status = error.response?.status || 500; ctx.body = { success: false, message: '登录失败,请检查账号密码' }; } }); module.exports = router;
步骤4:在后续请求中验证JWT
之后需要权限验证的接口,直接从ctx.session.jwt取出JWT,用jsonwebtoken验证即可:
// 接上面的路由文件 const jwt = require('jsonwebtoken'); router.get('/protected-resource', async (ctx) => { const jwtToken = ctx.session.jwt; if (!jwtToken) { ctx.status = 401; ctx.body = { success: false, message: '未登录,请先登录' }; return; } try { // 验证JWT,这里的密钥要和第三方生成JWT时用的一致 const decodedToken = jwt.verify(jwtToken, '第三方JWT密钥'); ctx.body = { success: true, data: decodedToken }; } catch (error) { ctx.status = 401; ctx.body = { success: false, message: '登录已过期,请重新登录' }; // 验证失败时清空session(即删除Cookie) ctx.session = null; } });
一些关键注意事项
- Cookie过期时间要和JWT一致:不然会出现Cookie还在但JWT已经失效的情况,影响用户体验。
- JWT大小限制:如果第三方返回的JWT太长(超过4KB左右),浏览器会拒绝存储Cookie,这时候建议用Redis来存JWT,koa-generic-session可以配置Redis存储,此时Cookie里只会存一个sessionId,安全性更高。
- 签名密钥要安全:不要把
app.keys里的密钥硬编码在代码里,用环境变量(比如dotenv)管理更安全。 - 跨域场景配置:如果前端和后端跨域,要确保后端配置了
Access-Control-Allow-Credentials: true,前端请求时也要设置withCredentials: true,不然Cookie不会被携带。
内容的提问来源于stack exchange,提问作者Yuri Shapkarin
相关产品推荐
相关产品推荐

