"use strict"; import crypto from "crypto" import logger from './logger.js' function AuthToken() { } AuthToken.prototype.init = function (redisdb, defaultExpiresSeconds) { this.tokenDB = redisdb; this.defaultExpiresSeconds = defaultExpiresSeconds; } AuthToken.prototype.gen = async function (uid, tokenOld) { let userToken = tokenOld; try { let tokenData = await this.tokenDB.get(userToken).then(function (data) { return JSON.parse(data); }); if (!tokenData) { if (!userToken || userToken.length <= 16) { let hash = crypto.createHash("md5"); hash.update(uid + Date() + Math.random()); userToken = hash.digest("hex"); } tokenData = { uid, token: userToken, ts: Math.floor(Date.now() / 1000), ttl: this.defaultExpiresSeconds, }; } this.tokenDB.set(userToken, JSON.stringify(tokenData), "EX", this.defaultExpiresSeconds); } catch (err) { logger.error('生成Token失败:', { error: err.message, uid, stack: err.stack }); } return userToken; }; AuthToken.prototype.update = async function (userToken) { try { let tokenData = await this.tokenDB.get(userToken).then(function (data) { return JSON.parse(data); }); if (tokenData) { this.tokenDB.set(userToken, JSON.stringify(tokenData), "EX", this.defaultExpiresSeconds); return tokenData; } } catch (err) { logger.error('更新Token失败:', { error: err.message, stack: err.stack }); } return null; }; AuthToken.prototype.del = async function (userToken) { let tokenData = await this.tokenDB.get(userToken).then(function (data) { return JSON.parse(data); }); if (tokenData) { this.tokenDB.del(userToken); } return tokenData; }; AuthToken.prototype.check = async function (userToken, updateExpire = true) { try { if (updateExpire) { if (await this.tokenDB.expire(userToken, this.defaultExpiresSeconds) >= 1) { return true; } } else { if (await this.tokenDB.exists([userToken]) >= 1) { return true; } } } catch (err) { logger.error('检查Token失败:', { error: err.message, userToken, stack: err.stack }); } return false; }; AuthToken.prototype.get = async function (token) { let tokenData = await this.tokenDB.get(token).then(function (data) { return JSON.parse(data); }); if (!tokenData) { return null; } return tokenData; }; AuthToken.prototype.koaRequest = async function (ctx, next) { try { let token = ctx.request.body.token; if (!token) token = ctx.request.query.token; if (!token) token = ctx.header["authorization"]; if (!token) token = ctx.header["token"]; if (!token) { throw new Error("Need token param."); } let ret = await this.check(token); if (!ret) { throw new Error("User not login in."); } let tokenData = await this.get(token); if (tokenData && tokenData.uid) { const { DBModel } = await import("../models/index.js"); const user = await DBModel.User.findOne({ _id: tokenData.uid }); if (user) { ctx.userInfo = user; } } ctx.authToken = this; return next(); } catch (err) { logger.error('身份验证失败:', { error: err.message, token: ctx.request.body.token || ctx.request.query.token || ctx.header["authorization"] || ctx.header["token"], stack: err.stack }); throw err; } }; const Token = new AuthToken() export { Token }