| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- import jwt, { SignOptions } from 'jsonwebtoken';
- import { UserEntity } from '../modules/users/user.entity';
- import debug from 'debug';
- const logger = {
- info: debug('backend:jwt:info'),
- error: debug('backend:jwt:error')
- };
- const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';
- const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || '7d';
- export interface JWTPayload {
- id: number;
- username: string;
- roles?: string[];
- openid?: string;
- }
- export class JWTUtil {
- /**
- * 生成 JWT token
- * @param user 用户实体
- * @param additionalPayload 额外的 payload 数据
- * @param expiresIn 过期时间
- * @returns JWT token
- */
- static generateToken(user: UserEntity, additionalPayload: Partial<JWTPayload> = {}, expiresIn?: string): string {
- if (!user.id || !user.username) {
- throw new Error('用户ID和用户名不能为空');
- }
- const payload: JWTPayload = {
- id: user.id,
- username: user.username,
- roles: user.roles?.map(role => role.name) || [],
- openid: user.openid || undefined,
- ...additionalPayload
- };
- try {
- const options: SignOptions = {
- expiresIn: expiresIn || JWT_EXPIRES_IN as SignOptions['expiresIn']
- };
- return jwt.sign(payload, JWT_SECRET, options);
- } catch (error) {
- logger.error('生成JWT token失败:', error);
- throw new Error('生成token失败');
- }
- }
- /**
- * 验证 JWT token
- * @param token JWT token
- * @returns 验证后的 payload
- */
- static verifyToken(token: string): JWTPayload {
- try {
- return jwt.verify(token, JWT_SECRET) as JWTPayload;
- } catch (error) {
- logger.error('验证JWT token失败:', error);
- throw new Error('无效的token');
- }
- }
- /**
- * 解码 JWT token(不验证签名)
- * @param token JWT token
- * @returns 解码后的 payload
- */
- static decodeToken(token: string): JWTPayload | null {
- try {
- return jwt.decode(token) as JWTPayload;
- } catch (error) {
- logger.error('解码JWT token失败:', error);
- return null;
- }
- }
- /**
- * 获取 token 的剩余有效期(秒)
- * @param token JWT token
- * @returns 剩余有效期(秒),如果 token 无效则返回 0
- */
- static getTokenRemainingTime(token: string): number {
- try {
- const decoded = jwt.verify(token, JWT_SECRET) as JWTPayload & { exp: number };
- const currentTime = Math.floor(Date.now() / 1000);
- return Math.max(0, decoded.exp - currentTime);
- } catch (error) {
- return 0;
- }
- }
- }
|