131 lines
3.2 KiB
JavaScript
131 lines
3.2 KiB
JavaScript
'use strict';
|
||
|
||
const crypto = require('crypto');
|
||
const Redis = require('ioredis');
|
||
|
||
function AuthToken(redisdb, expiresSeconds) {
|
||
this.tokenDB = redisdb;
|
||
this.defaultExpiresSeconds = expiresSeconds;
|
||
}
|
||
|
||
// 创建一条Redis记录,并生成Token
|
||
AuthToken.prototype.genToken = async function ({ userData, userApp }) {
|
||
// 生成系统内部的user token
|
||
let hash = crypto.createHash('md5');
|
||
hash.update(JSON.stringify(userData) + Date() + Math.random());
|
||
let userToken = hash.digest('hex');
|
||
|
||
// 缓存到redis
|
||
let tokenData = {
|
||
userData: userData,
|
||
apps: {},
|
||
createts: Math.floor(Date.now() / 1000),
|
||
ttl: this.defaultExpiresSeconds
|
||
};
|
||
tokenData.apps[userApp.appid] = userApp;
|
||
|
||
await this.tokenDB.set(userToken, JSON.stringify(tokenData), 'EX', this.defaultExpiresSeconds);
|
||
|
||
return userToken;
|
||
};
|
||
|
||
// 更新Token数据
|
||
AuthToken.prototype.update = async function (userToken, { userData, userApp, ttl }) {
|
||
let tokenData = await this.tokenDB.get(userToken).then(function (data) {
|
||
return JSON.parse(data);
|
||
});
|
||
|
||
if (tokenData) {
|
||
if (userData) tokenData.userData = userData;
|
||
if (userApp) tokenData.apps[userApp.appid] = userApp;
|
||
if (ttl) tokenData.ttl = ttl;
|
||
await this.tokenDB.set(userToken, JSON.stringify(tokenData), 'EX', this.defaultExpiresSeconds);
|
||
return tokenData;
|
||
}
|
||
|
||
return null
|
||
};
|
||
|
||
// 删除Token记录
|
||
AuthToken.prototype.delToken = async function (userToken) {
|
||
let tokenData = await this.tokenDB.get(userToken).then(function (data) {
|
||
return JSON.parse(data);
|
||
});
|
||
|
||
if (tokenData) {
|
||
this.tokenDB.del(userToken);
|
||
}
|
||
};
|
||
|
||
// 检查Token是否存在
|
||
AuthToken.prototype.checkToken = async function (userToken, updateExpire = true) {
|
||
let tokenData = await this.tokenDB.get(userToken).then(function (data) {
|
||
return JSON.parse(data);
|
||
});
|
||
|
||
// token不存在
|
||
if (!tokenData) {
|
||
return null;
|
||
}
|
||
|
||
if (updateExpire) {
|
||
this.tokenDB.expires(userToken, tokenData.ttl)
|
||
}
|
||
|
||
return tokenData;
|
||
};
|
||
|
||
// 获取Token数据
|
||
AuthToken.prototype.getTokenData = 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.checkTokenKoaRequest = 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 tokenData = await this.checkToken(token);
|
||
if (!tokenData) {
|
||
ctx.body = { code: 401, msg: 'User token not exist.', data: {} };
|
||
return;
|
||
}
|
||
|
||
ctx.userData = tokenData.userData;
|
||
|
||
let appid = ctx.request.body.appid;
|
||
if (!appid) appid = ctx.header['appid'];
|
||
if (appid) ctx.userApp = tokenData.apps[appid];
|
||
|
||
return next();
|
||
};
|
||
|
||
/*
|
||
AuthToken.prototype.checkTokenKoaRequestByAgent = async function (ctx, next) {
|
||
return this.checkTokenKoaRequest(ctx, ctx.userAgent.source, true, next);
|
||
};
|
||
*/
|
||
|
||
|
||
let tokenInstance = null;
|
||
module.exports = function getTokenInstance(redisdb) {
|
||
if (!tokenInstance) {
|
||
tokenInstance = new AuthToken(redisdb);
|
||
}
|
||
return tokenInstance;
|
||
};
|