"use strict"; const crypto = require("crypto"); const Redis = require("ioredis"); function AuthToken(redisdb, defaultExpiresSeconds) { this.tokenDB = redisdb; this.defaultExpiresSeconds = defaultExpiresSeconds; } // 创建一条Redis记录,并生成Token AuthToken.prototype.gen = async function ({ uid, appid }) { let userToken = ''; try { // 生成系统内部的user token let hash = crypto.createHash("md5"); hash.update(uid + Date() + Math.random()); userToken = hash.digest("hex"); // 缓存到redis let tokenData = { uid, appids: [appid], ts: Math.floor(Date.now() / 1000), ttl: this.defaultExpiresSeconds, }; let ret = await this.tokenDB.set(userToken, JSON.stringify(tokenData), "EX", this.defaultExpiresSeconds); if (ret != 'OK') { console.log('set token to redis db fail:' + ret); } } catch (err) { console.log(err) } return userToken; }; // 更新Token数据 AuthToken.prototype.update = async function (userToken, { appid }) { try { let tokenData = await this.tokenDB.get(userToken).then(function (data) { return JSON.parse(data); }); if (tokenData) { if (appid && !(appid in tokenData.appids)) { tokenData.appids.push(appid); } let ret = await this.tokenDB.set(userToken, JSON.stringify(tokenData), "EX", this.defaultExpiresSeconds); if (ret != 'OK') { console.log('set token to redis db fail:' + ret); } return tokenData; } } catch (err) { console.log(err) } return null; }; // 删除Token记录 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; }; // 检查Token是否存在 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) { console.log(err); } return false; }; // 获取Token数据 AuthToken.prototype.get = async function (userToken) { let tokenData = await this.tokenDB.get(userToken).then(function (data) { return JSON.parse(data); }); // token不存在 if (!tokenData) { return null; } return tokenData; }; AuthToken.prototype.koaRequest = async function (ctx, next) { let token = ctx.request.body.token; if (!token) token = ctx.header["authorization"]; if (!token) token = ctx.header["token"]; if (!token) { ctx.body = { code: 401, msg: "Need user token.", data: {} }; return; } let ret = await this.check(token); if (!ret) { ctx.body = { code: 401, msg: "User token not exist.", data: {} }; return; } ctx.authToken = this; return next(); }; let tokenInstance = null; module.exports = function getTokenInstance(redisdb, defaultExpiresSeconds) { if (!tokenInstance) { tokenInstance = new AuthToken(redisdb, defaultExpiresSeconds); } return tokenInstance; };