Egg框架集成JWT实现Token认证机制详解

一、JWT认证机制的核心价值

Token认证作为现代Web应用的核心安全机制,通过令牌替代传统Session实现无状态认证。JWT(JSON Web Token)凭借其自包含、跨域支持、标准化等特性,成为行业主流技术方案。相较于传统Session,JWT具备三大核心优势:

  1. 无状态化设计:认证信息直接编码在Token中,服务器无需存储会话数据,显著降低存储开销
  2. 跨域友好性:Token通过HTTP Header传输,天然支持分布式架构下的跨域认证
  3. 安全增强:支持数字签名、加密和过期时间控制,有效防范篡改和重放攻击

在Egg框架中集成JWT,能够快速构建符合RESTful规范的认证体系,特别适用于微服务架构和前后端分离场景。

二、Egg框架集成JWT的实现路径

2.1 环境准备与依赖安装

  1. npm install jsonwebtoken egg-jwt --save

其中jsonwebtoken是JWT核心库,egg-jwt是Egg插件,提供更贴合框架的封装。

2.2 插件配置与中间件注册

config/plugin.js中启用插件:

  1. exports.jwt = {
  2. enable: true,
  3. package: 'egg-jwt'
  4. };

配置config/config.default.js

  1. config.jwt = {
  2. secret: 'your_secret_key', // 加密密钥
  3. expiresIn: '24h', // Token有效期
  4. ignore: ['/api/public'] // 免认证路由
  5. };

2.3 核心功能实现

2.3.1 Token生成服务

创建app/service/token.js

  1. const jwt = require('jsonwebtoken');
  2. const Service = require('egg').Service;
  3. class TokenService extends Service {
  4. generate(payload, options = {}) {
  5. const { secret, expiresIn } = this.config.jwt;
  6. return jwt.sign(payload, secret, {
  7. expiresIn: expiresIn,
  8. ...options
  9. });
  10. }
  11. }

2.3.2 认证中间件实现

创建app/middleware/auth.js

  1. module.exports = (options, app) => {
  2. return async function auth(ctx, next) {
  3. const token = ctx.header.authorization;
  4. if (!token) {
  5. ctx.throw(401, 'No token provided');
  6. }
  7. try {
  8. const decoded = app.jwt.verify(token.split(' ')[1], options.secret);
  9. ctx.state.user = decoded;
  10. await next();
  11. } catch (err) {
  12. ctx.throw(401, 'Invalid token');
  13. }
  14. };
  15. };

2.3.3 控制器层实现

登录接口示例:

  1. const Controller = require('egg').Controller;
  2. class UserController extends Controller {
  3. async login() {
  4. const { ctx } = this;
  5. const { username, password } = ctx.request.body;
  6. // 验证用户逻辑
  7. const user = await ctx.model.User.findOne({ username });
  8. if (!user || user.password !== password) {
  9. ctx.throw(401, 'Authentication failed');
  10. }
  11. // 生成Token
  12. const token = ctx.service.token.generate({
  13. id: user.id,
  14. username: user.username
  15. });
  16. ctx.body = { token };
  17. }
  18. }

三、安全优化与最佳实践

3.1 密钥管理方案

  • 采用环境变量存储密钥:process.env.JWT_SECRET
  • 定期轮换密钥(建议每90天)
  • 生产环境使用RSA非对称加密:
    1. config.jwt = {
    2. secret: {
    3. public: fs.readFileSync('./public.pem'),
    4. private: fs.readFileSync('./private.pem')
    5. },
    6. algorithm: 'RS256'
    7. };

3.2 Token防护策略

  1. HttpOnly Cookie:防止XSS攻击窃取Token
    1. ctx.cookies.set('token', token, {
    2. httpOnly: true,
    3. signed: true
    4. });
  2. 短期有效:设置合理的过期时间(建议2小时以内)
  3. 刷新机制:实现Refresh Token延长会话

3.3 性能优化方案

  • 使用缓存存储用户基础信息,减少JWT解析次数
  • 对高频接口采用Token白名单机制
  • 启用Gzip压缩传输的Token

四、常见问题解决方案

4.1 Token过期处理

实现中间件捕获TokenExpiredError:

  1. app.use(async (ctx, next) => {
  2. try {
  3. await next();
  4. } catch (err) {
  5. if (err.name === 'TokenExpiredError') {
  6. ctx.status = 401;
  7. ctx.body = { code: 401, message: 'Token expired' };
  8. }
  9. }
  10. });

4.2 跨域问题处理

配置config/config.default.js

  1. config.security = {
  2. csrf: {
  3. enable: false
  4. },
  5. domainWhiteList: ['*'] // 生产环境应指定具体域名
  6. };
  7. config.cors = {
  8. origin: '*',
  9. allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH'
  10. };

4.3 移动端适配建议

  • 实现Token自动刷新机制
  • 添加设备指纹校验
  • 限制单设备登录

五、扩展应用场景

  1. 微服务认证:通过JWT实现服务间认证
  2. 单点登录:构建企业级SSO系统
  3. API网关:集成JWT验证作为统一入口
  4. IoT设备认证:为低功耗设备提供轻量级认证

六、测试验证方案

6.1 单元测试示例

  1. const { app, assert } = require('egg-mock/bootstrap');
  2. describe('test/app/controller/user.test.js', () => {
  3. it('should login success', async () => {
  4. const result = await app.httpRequest()
  5. .post('/api/login')
  6. .send({ username: 'test', password: '123456' })
  7. .expect(200);
  8. assert(result.body.token);
  9. });
  10. });

6.2 性能测试指标

  • 生成Token耗时:<5ms
  • 验证Token耗时:<2ms
  • QPS支持:>5000(单核4G内存)

通过上述完整方案,开发者可以在Egg框架中快速构建安全可靠的JWT认证体系。实际开发中需根据业务场景调整安全策略,建议定期进行安全审计和性能调优。对于高并发场景,可考虑结合Redis实现Token黑名单机制,进一步提升系统安全性。