2020-12-04 20:21:12 +08:00
|
|
|
|
"use strict";
|
2019-08-28 14:08:14 +08:00
|
|
|
|
|
2020-12-04 20:21:12 +08:00
|
|
|
|
const crypto = require("crypto");
|
|
|
|
|
const Redis = require("ioredis");
|
2019-08-28 14:08:14 +08:00
|
|
|
|
|
2020-12-04 20:21:12 +08:00
|
|
|
|
function AuthToken(redisdb, defaultExpiresSeconds) {
|
2019-09-04 09:00:31 +08:00
|
|
|
|
this.tokenDB = redisdb;
|
2020-12-04 20:21:12 +08:00
|
|
|
|
this.defaultExpiresSeconds = defaultExpiresSeconds;
|
2019-08-28 14:08:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-12-04 14:32:39 +08:00
|
|
|
|
// 创建一条Redis记录,并生成Token
|
2020-12-04 20:21:12 +08:00
|
|
|
|
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)
|
|
|
|
|
}
|
2019-08-28 14:08:14 +08:00
|
|
|
|
|
|
|
|
|
return userToken;
|
|
|
|
|
};
|
|
|
|
|
|
2020-12-04 14:32:39 +08:00
|
|
|
|
// 更新Token数据
|
2020-12-04 20:21:12 +08:00
|
|
|
|
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)
|
2020-12-04 14:31:54 +08:00
|
|
|
|
}
|
2020-12-04 14:32:39 +08:00
|
|
|
|
|
2020-12-04 20:21:12 +08:00
|
|
|
|
return null;
|
2020-12-04 14:31:54 +08:00
|
|
|
|
};
|
|
|
|
|
|
2020-12-04 14:32:39 +08:00
|
|
|
|
// 删除Token记录
|
2020-12-04 20:21:12 +08:00
|
|
|
|
AuthToken.prototype.del = async function (userToken) {
|
2020-06-29 13:18:38 +08:00
|
|
|
|
let tokenData = await this.tokenDB.get(userToken).then(function (data) {
|
2019-08-28 14:08:14 +08:00
|
|
|
|
return JSON.parse(data);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (tokenData) {
|
|
|
|
|
this.tokenDB.del(userToken);
|
|
|
|
|
}
|
2020-12-05 08:50:51 +08:00
|
|
|
|
|
|
|
|
|
return tokenData;
|
2019-08-28 14:08:14 +08:00
|
|
|
|
};
|
|
|
|
|
|
2020-12-04 14:32:39 +08:00
|
|
|
|
// 检查Token是否存在
|
2020-12-04 20:21:12 +08:00
|
|
|
|
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);
|
2020-06-29 13:18:38 +08:00
|
|
|
|
}
|
2020-12-04 20:21:12 +08:00
|
|
|
|
return false;
|
2019-08-28 14:08:14 +08:00
|
|
|
|
};
|
|
|
|
|
|
2020-12-04 14:32:39 +08:00
|
|
|
|
// 获取Token数据
|
2020-12-04 20:21:12 +08:00
|
|
|
|
AuthToken.prototype.get = async function (userToken) {
|
2020-06-29 13:18:38 +08:00
|
|
|
|
let tokenData = await this.tokenDB.get(userToken).then(function (data) {
|
2019-08-28 14:08:14 +08:00
|
|
|
|
return JSON.parse(data);
|
|
|
|
|
});
|
2020-06-29 13:18:38 +08:00
|
|
|
|
|
|
|
|
|
// token不存在
|
2019-08-28 14:08:14 +08:00
|
|
|
|
if (!tokenData) {
|
2020-06-29 13:18:38 +08:00
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return tokenData;
|
|
|
|
|
};
|
|
|
|
|
|
2020-12-04 20:21:12 +08:00
|
|
|
|
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"];
|
2020-06-29 13:18:38 +08:00
|
|
|
|
|
|
|
|
|
if (!token) {
|
2020-12-04 20:21:12 +08:00
|
|
|
|
ctx.body = { code: 401, msg: "Need user token.", data: {} };
|
2019-08-28 14:08:14 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-04 20:21:12 +08:00
|
|
|
|
let ret = await this.check(token);
|
|
|
|
|
if (!ret) {
|
|
|
|
|
ctx.body = { code: 401, msg: "User token not exist.", data: {} };
|
2020-02-25 15:41:50 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
2020-12-04 14:31:54 +08:00
|
|
|
|
|
2019-08-28 14:08:14 +08:00
|
|
|
|
return next();
|
|
|
|
|
};
|
|
|
|
|
|
2019-09-04 09:00:31 +08:00
|
|
|
|
let tokenInstance = null;
|
2020-12-04 20:21:12 +08:00
|
|
|
|
module.exports = function getTokenInstance(redisdb, defaultExpiresSeconds) {
|
2019-09-04 09:00:31 +08:00
|
|
|
|
if (!tokenInstance) {
|
2020-12-04 20:21:12 +08:00
|
|
|
|
tokenInstance = new AuthToken(redisdb, defaultExpiresSeconds);
|
2019-09-04 09:00:31 +08:00
|
|
|
|
}
|
|
|
|
|
return tokenInstance;
|
|
|
|
|
};
|