2019-08-28 14:08:14 +08:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
const crypto = require('crypto');
|
|
|
|
const Redis = require('ioredis');
|
|
|
|
|
|
|
|
function AuthToken(redisOpt) {
|
|
|
|
if (!(this instanceof AuthToken)) {
|
|
|
|
return new AuthToken(redisOpt);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!redisOpt) {
|
|
|
|
throw 'AuthToken: need redis config.';
|
|
|
|
}
|
|
|
|
|
|
|
|
this.tokenDB = new Redis(redisOpt);
|
|
|
|
this.tokenDB.on("connect",function(){
|
|
|
|
console.log("AuthToken: ioredis connected: " + JSON.stringify(redisOpt));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
AuthToken.prototype.genToken = async function(userData, expiresSeconds) {
|
|
|
|
// 生成系统内部的user token
|
|
|
|
let hash = crypto.createHash('md5');
|
|
|
|
hash.update(JSON.stringify(userData));
|
|
|
|
let userToken = hash.digest('hex');
|
|
|
|
|
|
|
|
// 缓存到redis
|
|
|
|
let tokenData = {
|
|
|
|
userData: userData,
|
|
|
|
expires: {ttl: expiresSeconds, ts: Math.floor(Date.now() / 1000)}
|
|
|
|
};
|
2019-08-28 14:25:56 +08:00
|
|
|
await this.tokenDB.set(userToken, JSON.stringify(tokenData), 'EX', expiresSeconds);
|
2019-08-28 14:08:14 +08:00
|
|
|
|
|
|
|
return userToken;
|
|
|
|
};
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
AuthToken.prototype.checkToken = async function (userToken) {
|
|
|
|
let tokenData = await this.tokenDB.get(userToken).then(function(data) {
|
|
|
|
return JSON.parse(data);
|
|
|
|
});
|
|
|
|
|
|
|
|
// token不存在
|
|
|
|
if (!tokenData) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
tokenData.expires.ts = Math.floor(Date.now() / 1000);
|
|
|
|
this.tokenDB.set(userToken, JSON.stringify(tokenData), 'EX', tokenData.expires.ttl);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
AuthToken.prototype.checkTokenKoaRequest = async function (ctx, next) {
|
|
|
|
if (!ctx.request.body.token) {
|
|
|
|
ctx.body = {
|
|
|
|
result: 'fail', error: { code: 401, msg: 'Need user token.' }, data: {}
|
|
|
|
};
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let tokenData = await this.tokenDB.get(ctx.request.body.token).then(function(data) {
|
|
|
|
return JSON.parse(data);
|
|
|
|
});
|
|
|
|
if (!tokenData) {
|
|
|
|
ctx.body = {
|
|
|
|
result: 'fail', error: { code: 401, msg: 'User token error.' }, data: {}
|
|
|
|
};
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx.userData = tokenData.userData;
|
|
|
|
|
|
|
|
//
|
|
|
|
tokenData.expires.ts = Math.floor(Date.now() / 1000);
|
|
|
|
this.tokenDB.set(ctx.request.body.token, JSON.stringify(tokenData), 'EX', tokenData.expires.ttl);
|
|
|
|
|
|
|
|
return next();
|
|
|
|
};
|
|
|
|
|
|
|
|
AuthToken.prototype.checkTokenKoaRequestPost = async function (ctx, next) {
|
|
|
|
if (ctx.req.method === 'POST') {
|
|
|
|
return this.checkTokenKoaRequest(ctx, next);
|
|
|
|
}
|
|
|
|
|
|
|
|
next();
|
|
|
|
};
|
|
|
|
|
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = AuthToken;
|