12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485 |
- 'use strict';
- const { CrudService } = require('naf-framework-mongoose-free/lib/service');
- const { BusinessError, ErrorCode } = require('naf-core').Error;
- const _ = require('lodash');
- const assert = require('assert');
- const { ObjectId } = require('mongoose').Types;
- //
- class TokenService extends CrudService {
- constructor(ctx) {
- super(ctx, 'token');
- this.redis = this.app.redis;
- this.tokenTimes = 2; // token的使用次数
- this.tokenTimeOut = 5 * 60; // x * 60s;token超时时间
- }
- /**
- * 生成token
- * token用于检测是否允许请求接口
- * 每个用户的每个token有使用次数(上面设置的),
- * @param {String} id 用户信息id
- * @property {String} oid 随机ObjectId作为key,在redis中也是使用这个作为key
- */
- async initToken(id) {
- // 生成混合id
- const oid = ObjectId().toString();
- const arr = [];
- // 将用户id翻转
- const idArr = _.reverse(oid.split(''));
- const oidArr = id.split('');
- // 将用户id和混合id进行穿插组合
- for (let i = 0; i < idArr.length; i++) {
- const v = idArr[i];
- const s = oidArr[i];
- arr.push(v, s);
- }
- // 拼接成要返回的token的键
- const tokenKey = arr.join('');
- // 设置该用户的token次数
- await this.redis.set(`token:${oid}`, this.tokenTimes, 'ex', this.tokenTimeOut);
- return tokenKey;
- }
- /**
- * 从token中取出用户id
- * @param {String} str token
- * @return {String} uid 用户id/oid redis的key
- */
- getIdFromToken(str) {
- const idArr = str.split('');
- const arr = [];
- const uArr = [];
- for (let i = 0; i < idArr.length; i += 2) {
- arr.push(idArr[i]);
- if (idArr[i + 1]) uArr.push(idArr[i + 1]);
- }
- const oid = _.reverse(arr).join('');
- const uid = uArr.join('');
- return { oid, uid };
- }
- /**
- * 检查并使用token
- * @param {String} token token
- */
- async useToken(token) {
- const { oid, uid } = this.getIdFromToken(token);
- let tvalue = await this.redis.get(`token:${oid}`);
- if (!(tvalue && parseInt(tvalue))) return { token, check: false };
- tvalue = parseInt(tvalue);
- if (tvalue - 1 <= 0) {
- // 把上个token删了
- await this.redis.del(`token:${oid}`);
- // 该token用完了,换下一个
- const newToken = await this.initToken(uid);
- return { token: newToken, check: true, fresh: true };
- }
- // token使用次数-1
- tvalue--;
- await this.redis.set(`token:${oid}`, tvalue);
- return { token, check: true };
- }
- }
- module.exports = TokenService;
|