const jwt = require('jsonwebtoken'); const logger = require('./logger'); /** * JWT 工具类 * 提供 token 生成、验证、刷新等功能 */ class JWTUtils { constructor() { this.secret = process.env.JWT_SECRET || 'your-secret-key'; this.refreshSecret = process.env.JWT_REFRESH_SECRET || 'your-refresh-secret-key'; // Access token 过期时间(默认 2 小时) this.accessTokenExpiry = process.env.JWT_ACCESS_EXPIRY || '24h'; // Refresh token 过期时间(默认 7 天) this.refreshTokenExpiry = process.env.JWT_REFRESH_EXPIRY || '7d'; } /** * 生成访问令牌 * @param {Object} payload - 用户信息载荷 * @returns {String} access token */ generateAccessToken(payload) { const data = { userId: payload.userId, username: payload.username, corpId: payload.corpId, role: payload.role, type: 'access', platform: payload.platform || '', }; return jwt.sign(data, this.secret, { expiresIn: this.accessTokenExpiry, issuer: 'zyt-hlw-service' }); } /** * 生成刷新令牌 * @param {Object} payload - 用户信息载荷 * @returns {String} refresh token */ generateRefreshToken(payload) { const data = { userId: payload.userId, username: payload.username, type: 'refresh' }; return jwt.sign(data, this.refreshSecret, { expiresIn: this.refreshTokenExpiry, issuer: 'zyt-hlw-service' }); } /** * 生成访问令牌和刷新令牌 * @param {Object} payload - 用户信息载荷 * @returns {Object} { accessToken, refreshToken } */ generateTokens(payload) { const accessToken = this.generateAccessToken(payload); const refreshToken = this.generateRefreshToken(payload); return { accessToken, refreshToken, expiresIn: this.parseExpiry(this.accessTokenExpiry) }; } /** * 验证访问令牌 * @param {String} token - 访问令牌 * @returns {Object} 解码后的载荷 */ verifyAccessToken(token) { return jwt.verify(token, this.secret); } /** * 验证刷新令牌 * @param {String} token - 刷新令牌 * @returns {Object} 解码后的载荷 */ verifyRefreshToken(token) { return jwt.verify(token, this.refreshSecret); } /** * 使用刷新令牌生成新的访问令牌 * @param {String} refreshToken - 刷新令牌 * @returns {Object} { accessToken, expiresIn } */ refreshAccessToken(refreshToken) { const decoded = this.verifyRefreshToken(refreshToken); if (decoded.type !== 'refresh') { throw new Error('Invalid token type'); } // 生成新的访问令牌 const accessToken = this.generateAccessToken({ userId: decoded.userId, username: decoded.username }); return { accessToken, expiresIn: this.parseExpiry(this.accessTokenExpiry) }; } /** * 解析过期时间字符串为秒数 * @param {String} expiry - 过期时间字符串(如 '2h', '7d') * @returns {Number} 秒数 */ parseExpiry(expiry) { const match = expiry.match(/^(\d+)([smhd])$/); if (!match) return 7200; // 默认 2 小时 const value = parseInt(match[1]); const unit = match[2]; const multipliers = { 's': 1, 'm': 60, 'h': 3600, 'd': 86400 }; return value * (multipliers[unit] || 3600); } /** * 解码 token(不验证签名) * @param {String} token * @returns {Object} 解码后的载荷 */ decode(token) { return jwt.decode(token); } } // 导出单例 module.exports = new JWTUtils();