加密:接口加密解密

This commit is contained in:
luying
2022-06-16 19:14:05 +08:00
parent 144f3ed0b0
commit 469e393f5e
18 changed files with 833 additions and 162 deletions

View File

@@ -229,7 +229,6 @@ function setupFilters(app: _pinus.Application) {
app.filter(globalFilter(app));
app.globalAfter((err: Error, routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, resp: any, cb: HandlerCallback) => {
infologger.debug('global after ', JSON.stringify(routeRecord), msg && msg.route, msg && JSON.stringify(msg.body), resp && JSON.stringify(resp), session && session.get('roleId'));
if (err) infologger.debug(err);
})

View File

@@ -1,5 +1,5 @@
import { Application, BackendSession, HandlerService, pinus, } from 'pinus';
import { aesEncrypt, aesEncryptcfb, resResult } from '../../../pubUtils/util';
import { resResult } from '../../../pubUtils/util';
import { ENCRYPT_IV, ENCRYPT_KEY, STATUS, TASK_TYPE } from '../../../consts';
import { ActivityGroupModel } from '../../../db/ActivityGroup';
import { ServerlistModel } from '../../../db/Serverlist';

View File

@@ -2,112 +2,204 @@ import {Application, RouteRecord, FrontendOrBackendSession, HandlerCallback, pin
// import { checkEvent } from '../../../services/eventSercive';
import { refresh } from '../../../services/refreshService';
import { checkPrivateChat, checkGuildChat, checkOtherChat, checkRoleName, checkGuildName } from "../../../services/sdkService";
import { resResult, checkWhiteList, genCode } from "../../../pubUtils/util";
import { resResult, genCode } from "../../../pubUtils/util";
import { checkWhiteList, MsgEncrypt } from "../../../pubUtils/sysUtil";
import { BLOCK_TYPE, CHANNEL_PREFIX, MSG_TYPE, PUSH_ROUTE, STATUS } from "../../../consts";
import { nowSeconds } from "../../../pubUtils/timeUtil";
import { getServerMainten } from "../../../services/gmService";
import { errlogger } from "../../../util/logger";
import { errlogger, infologger } from "../../../util/logger";
import { gameData } from "../../../pubUtils/data";
import { sendMessageToUser } from "../../../services/pushService";
import { isCheckWord } from "../../../pubUtils/sdkUtil";
import { isDevelopEnv } from "../../../services/utilService";
import { isNumber } from "underscore";
import { redisClient } from "../../../services/redisService";
export function globalFilter(app: Application) {
return new Filter(app);
}
var Filter = function(this: any, app: Application) {
this.app = app;
this.accessTime = new Map<string, number>();
};
class Filter {
private app: Application;
private accessTime = new Map<string, number>();
Filter.prototype.checkFrequency = function(route: string, msg: any, roleId: string) {
let protect = gameData.serverConst.PROTECT_API.find(cur => {
if(cur.route == route) {
let paramOK = true;
for(let key in cur.param) {
if(msg[key] != cur.param[key]) {
paramOK = false; break;
constructor(app: Application) {
this.app = app;
}
public async before (routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, next: HandlerCallback) {
const serverId: number = session.get('serverId');
const sid: string = session.get('sid');
const roleId: string = session.get('roleId');
const uid: number = session.get('userid');
const ip: string = session.get('ip');
// console.log('*********** global before ip', ip)
let guildCode = session.get('guildCode');
let blockType = session.get('blockType');
if(!this.checkPassEncrypt(routeRecord.route)) {
msg = this.decryptMsg(msg, session);
if(!msg) return next(new Error('globalFilter'), resResult(STATUS.WRONG_PARMS));
if(!this.checkTimeStamp(msg)) return next(new Error('globalFilter'), resResult(STATUS.TIMESTAMP_ERR));
if(!this.checkDuplicateAccess(msg)) return next(new Error('globalFilter'), resResult(STATUS.DUPLICATE_ACCESS))
}
// 访问频率控制
if(!this.checkFrequency(routeRecord.route, msg, roleId)) {
return next(new Error('globalFilter'), resResult(STATUS.ACCESS_BUSY));
}
if(!this.checkFunction(routeRecord.route)) {
return next(new Error('globalFilter'), resResult(STATUS.FUNCTION_CLOSE));
}
// 玩家屏蔽
if(blockType == BLOCK_TYPE.BLOCK) return next(new Error('globalFilter'), resResult(STATUS.BLOCKED));
if(blockType == BLOCK_TYPE.BAN && this.checkBanRoute(routeRecord.route)) {
return next(new Error('globalFilter'), resResult(STATUS.BANNED));
}
session.push('teamCode', () => {});
let hasNoBlockWords = isCheckWord(isDevelopEnv()) && this.checkHasBlockWord(routeRecord.route, msg, roleId, serverId, guildCode);
if(!hasNoBlockWords) return next(new Error('globalFilter'), resResult(STATUS.BLOCK_WORDS));
if(routeRecord.route == 'guild.guildHandler.createGuild') {
let guildCode = genCode(6);
msg.guildCode = guildCode;
}
if(await this.checkMainten(serverId, sid, ip, uid)) {
sendMessageToUser(roleId, PUSH_ROUTE.SERVER_MAINTENANCE, resResult(STATUS.SERVER_MAINTENANCE), sid);
return next(new Error('globalFilter'), resResult(STATUS.SERVER_MAINTENANCE));
}
next(null);
};
public async after (err: Error, routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, resp: any, next: HandlerCallback) {
//刷新
await refresh(session);
infologger.debug('global after ', routeRecord.route, msg && JSON.stringify(msg), resp && JSON.stringify(resp), session && session.get('roleId'));
if(!this.checkPassEncrypt(routeRecord.route)) {
let data = this.encryptMsg(resp, session);
if(!data) return next(new Error('response data err'));
resp = this.setResp(resp, data);
}
next(null);
};
// 检查调用频率
private checkFrequency (route: string, msg: any, roleId: string) {
let protect = gameData.serverConst.PROTECT_API.find(cur => {
if(cur.route == route) {
let paramOK = true;
for(let key in cur.param) {
if(msg[key] != cur.param[key]) {
paramOK = false; break;
}
}
if(paramOK) return true;
}
return false;
});
if(!protect) {
return true;
}
let keyOfRouteWithUser = `${protect.id}_${roleId}`;
if(this.accessTime && this.accessTime.has(keyOfRouteWithUser)) {
console.log(this.accessTime.get(keyOfRouteWithUser) - Date.now());
if(Date.now() - this.accessTime.get(keyOfRouteWithUser) < protect.interval) {
errlogger.info(`${keyOfRouteWithUser} 间隔时间小于${protect.interval}ms${Date.now() - this.accessTime.get(keyOfRouteWithUser)}`);
return false;
}
if(paramOK) return true;
}
return false;
});
if(!protect) {
}
if(!this.accessTime) this.accessTime = new Map<string, number>();
this.accessTime.set(keyOfRouteWithUser, Date.now());
return true;
}
let keyOfRouteWithUser = `${protect.id}_${roleId}`;
if(this.accessTime && this.accessTime.has(keyOfRouteWithUser)) {
console.log(this.accessTime.get(keyOfRouteWithUser) - Date.now());
if(Date.now() - this.accessTime.get(keyOfRouteWithUser) < protect.interval) {
errlogger.info(`${keyOfRouteWithUser} 间隔时间小于${protect.interval}ms${Date.now() - this.accessTime.get(keyOfRouteWithUser)}`);
return false;
// 检查该接口是否关闭
private checkFunction (route: string) {
if(gameData.serverConst.API_IS_CLOSE == 1) {
if(gameData.serverConst.CLOSE_APIS.indexOf(route) != -1) {
return false;
}
}
}
if(!this.accessTime) this.accessTime = new Map<string, number>();
this.accessTime.set(keyOfRouteWithUser, Date.now());
return true;
}
Filter.prototype.checkFunction = function(route: string) {
if(gameData.serverConst.API_IS_CLOSE == 1) {
if(gameData.serverConst.CLOSE_APIS.indexOf(route) != -1) {
return false;
}
}
return true;
}
Filter.prototype.before = async function (routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, next: HandlerCallback) {
const serverId: number = session.get('serverId');
const sid: string = session.get('sid');
const roleId: string = session.get('roleId');
const uid: number = session.get('userid');
const ip: string = session.get('ip');
// console.log('*********** global before ip', ip)
let guildCode = session.get('guildCode');
let blockType = session.get('blockType');
// 访问频率控制
if(!this.checkFrequency(routeRecord.route, msg, roleId)) {
return next(new Error('globalFilter'), resResult(STATUS.ACCESS_BUSY));
}
if(!this.checkFunction(routeRecord.route)) {
return next(new Error('globalFilter'), resResult(STATUS.FUNCTION_CLOSE));
return true;
}
// 玩家屏蔽
if(blockType == BLOCK_TYPE.BLOCK) return next(new Error('globalFilter'), resResult(STATUS.BLOCKED));
if(blockType == BLOCK_TYPE.BAN) {
if([
// 这个接口是否需要加密解密
private checkPassEncrypt (route: string) {
return route.startsWith('gm.');
}
// 解密接口
private decryptMsg (msg: any, session: FrontendOrBackendSession) {
let msgEncrypt = new MsgEncrypt({ encodeK: msg?.k, encodeV: msg?.v });
let { aesKey, aesIV } = msgEncrypt.getKv();
msg = this.setMsg(msg, msgEncrypt.decryptMsg(msg?.data));
if(!msg) return false;
session.set('k', aesKey);
session.set('v', aesIV);
session.push('k', () => {});
session.push('v', () => {});
return msg
}
// 解密接口
private encryptMsg (resp: any, session: FrontendOrBackendSession) {
let msgEncrypt = new MsgEncrypt({ k: session.get('k'), v: session.get('v')});
let data = msgEncrypt.encryptMsg(resp);
return data;
}
// 传入的msg的修改
private setMsg (msg:any, targetObj: any) {
if(!msg || !targetObj || typeof targetObj != 'object') {
return msg;
}
delete msg.k;
delete msg.v;
delete msg.data;
for(let key in targetObj) {
if(targetObj.hasOwnProperty(key)) {
msg[key] = targetObj[key];
}
}
return msg;
}
// 传出的resp的修改
private setResp(resp: any, data: string) {
for(let key in resp) {
if(resp.hasOwnProperty(key)) {
delete resp[key];
}
}
resp.data = data;
return resp;
}
// 禁言的接口
private checkBanRoute (route: string) {
return [
'chat.chatHandler.sendPrivateMessage',
'chat.chatHandler.sendGroupMessage',
'battle.comBattleHandler.sendTeamMsg',
'battle.barrageHandler.sendBarrage',
'guild.guildHandler.sendMail',
'guild.guildHandler.setGuildInfo',
].indexOf(routeRecord.route) != -1) {
return next(new Error('globalFilter'), resResult(STATUS.BANNED));
}
].indexOf(route) != -1
}
session.push('teamCode', () => {});
if(sid) {
const mainten = getServerMainten(serverId);
if(mainten) { // 该服务器维护
if(mainten.startTime > nowSeconds() || mainten.endTime < nowSeconds()) return next(null)
let isWhiteList = await checkWhiteList(this.app.get('env'), ip, uid, serverId);
if(isWhiteList) return next(null);
sendMessageToUser(roleId, PUSH_ROUTE.SERVER_MAINTENANCE, resResult(STATUS.SERVER_MAINTENANCE), sid);
return next(new Error('globalFilter'), resResult(STATUS.SERVER_MAINTENANCE));
}
}
let hasBlockWords = false;
if(isCheckWord(isDevelopEnv())) {
switch(routeRecord.route) {
// 检查聊天屏蔽词
private async checkHasBlockWord (route: string, msg: any, roleId: string, serverId: number, guildCode: string) {
let hasBlockWords = false;
switch(route) {
case 'chat.chatHandler.sendPrivateMessage':
{
if(msg.type == MSG_TYPE.IMG) break;
@@ -161,26 +253,39 @@ Filter.prototype.before = async function (routeRecord: RouteRecord, msg: any, se
break;
}
}
return hasBlockWords;
}
if(routeRecord.route == 'guild.guildHandler.createGuild') {
let guildCode = genCode(6);
msg.guildCode = guildCode;
// 检查是否维护中
private async checkMainten(serverId: number, sid: string, ip: string, uid: number) {
if(!sid) return false;
const mainten = getServerMainten(serverId);
if(!mainten) return false // 该服务器维护
if(mainten.startTime > nowSeconds() || mainten.endTime < nowSeconds()) return false;
let isWhiteList = await checkWhiteList(this.app.get('env'), ip, uid, serverId);
if(isWhiteList) return false;
return true
}
if(hasBlockWords) return next(new Error('globalFilter'), resResult(STATUS.BLOCK_WORDS));
private checkTimeStamp(msg: { ts: number }) {
let ts = msg.ts;
delete msg.ts;
return isNumber(ts) && Date.now() - ts < gameData.serverConst.TIME_STAMP_OVER && Date.now() > ts;
}
next(null);
};
private async checkDuplicateAccess(msg: { cs: string }) {
let cs = msg.cs;
delete msg.cs;
let redis = redisClient();
if(await redis.existsAsync(`cs: ${cs}`)) {
return false
}
Filter.prototype.after = async function (err: Error, routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, resp: any, next: HandlerCallback) {
//刷新
await refresh(session);
// return checkEvent(session).then(()=>{
// next(err);
// }).catch(e => {
// console.error(e);
// next(err);
// }); // 奇遇本检查
next(null);
};
await redis.setAsync(`cs: ${cs}`, '');
await redis.expireAsync(`cs: ${cs}`, gameData.serverConst.ACCESS_CODE_EXPIRE_TIME/1000);
return true;
}
}

View File

@@ -32,7 +32,6 @@ import { SurveyRecModel } from "../db/SurveyRec";
import { getPopUpShopData } from "./activity/popUpShopService";
import { TaskPassData } from "../domain/activityField/taskPassField";
import { ActivityGroupModel } from "../db/ActivityGroup";
import { ActivityInRemote } from "../domain/activityField/activityField";
import { redisClient } from "./redisService";
// —————————————— 跑马灯 —————————————— //

View File

@@ -1,9 +1,10 @@
import { Channel, pinus } from "pinus";
import { CHANNEL_PREFIX, PUSH_BATCH, PUSH_INTERVAL, PUSH_ROUTE, STATUS } from "../consts";
import { resResult } from "../pubUtils/util";
import { genCode, resResult } from "../pubUtils/util";
import { getCityChannelSid, getGuildChannelSid, getWorldChannelSid, groupRoomId } from "./chatService";
import { getAllOnlineRoles, getRoleOnlineInfo } from "./redisService";
import { errlogger, infologger } from '../util/logger';
import { MsgEncrypt } from "../pubUtils/sysUtil";
export async function sendMessageToAllWithSuc(route: string, data: any, filterCb?: ({ lv, topLineupCe }) => boolean) {
await sendMessageToAll(route, resResult(STATUS.SUCCESS, data), filterCb);
@@ -84,14 +85,14 @@ export async function sendMessageToUsersWithSuc(route: string, data: any, uids:
// 推送给个人的方法收束于这个函数
export async function sendMessageToUsers(route: string, data: any, uids: { uid: string, sid: string }[]) {
if(uids.length > 0) {
pinus.app.get('channelService').pushMessageByUids(route, data, uids);
pinus.app.get('channelService').pushMessageByUids(route, encryptMsg(data), uids);
infologger.debug(`pushMessage route: ${route} data: ${JSON.stringify(data)} members: ${uids.map(obj => obj.uid).join()}`);
}
}
export async function sendMessageToTeam(teamCode: string, route: string, data: any) {
const channel = pinus.app.get('channelService').getChannel(teamCode);
sendMessageToChannel(channel, route, resResult(STATUS.SUCCESS, data));
sendMessageToChannel(channel, route, resResult(STATUS.SUCCESS, encryptMsg(data)));
}
/**
@@ -153,4 +154,27 @@ export function removeFromTeamChannel(teamCode: string, roleId: string) {
if (users.indexOf(roleId) !== -1) {
channel.removeMember(roleId);
}
}
}
function getKvFromMemory() {
let k = pinus.app.get('aeaKey');
let v = pinus.app.get('aesIV');
let kvRefTime = pinus.app.get('kvRefTime');
let now = new Date().setMinutes(0, 0, 0);
if(!kvRefTime || now - kvRefTime >= 60 * 60 * 1000) {
k = genCode(24);
v = genCode(16);
pinus.app.set('aeaKey', k);
pinus.app.set('aesIV', v);
pinus.app.set('kvRefTime', now);
}
return { k, v }
}
function encryptMsg(json: any) {
let kv = getKvFromMemory();
let msgEncrypt = new MsgEncrypt(kv);
let { aesKey, aesIV } = msgEncrypt.getEncodeKv();
let data = msgEncrypt.encryptMsg(json);
return { data, k: aesKey, v: aesIV }
}

View File

@@ -337,6 +337,7 @@ export async function roleLeave(roleId: string) {
await redisClient().hdelAsync(REDIS_KEY.ONLINE_CNT, roleId);
await redisClient().hdelAsync(REDIS_KEY.ONLINE_USERS, roleId);
await redisClient().hdelAsync(REDIS_KEY.USER_CODE, role.userCode);
await redisClient().hdelAsync(REDIS_KEY.ONLINE_CNT, roleId);
}
return role;
}
@@ -365,6 +366,7 @@ export async function getRoleOnlineInfo(roleId: string) {
try {
let result = str.split('|');
let [userCode, sid, createTime, serverId, lv, topLineupCe] = result;
return {
isOnline: true, userCode, sid,
createtime: parseInt(createTime),

View File

@@ -141,6 +141,11 @@
"@types/node": "*"
}
},
"@types/lodash": {
"version": "4.14.182",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz",
"integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q=="
},
"@types/mocha": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.0.tgz",
@@ -254,6 +259,17 @@
"debug": "4"
}
},
"ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"requires": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
},
"alipay-mobile": {
"version": "4.0.2",
"resolved": "https://registry.nlark.com/alipay-mobile/download/alipay-mobile-4.0.2.tgz",
@@ -341,6 +357,19 @@
"resolved": "https://registry.npm.taobao.org/arraybuffer.slice/download/arraybuffer.slice-0.0.7.tgz",
"integrity": "sha1-O7xCdd1YTMGxCAm4nU6LY6aednU="
},
"asn1": {
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
"integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
"requires": {
"safer-buffer": "~2.1.0"
}
},
"assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw=="
},
"assertion-error": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
@@ -376,6 +405,16 @@
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"aws-sign2": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
"integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA=="
},
"aws4": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
},
"babel-runtime": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
@@ -419,6 +458,14 @@
"node-pre-gyp": "0.15.0"
}
},
"bcrypt-pbkdf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
"integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
"requires": {
"tweetnacl": "^0.14.3"
}
},
"bearcat-buffer": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/bearcat-buffer/-/bearcat-buffer-0.1.1.tgz",
@@ -543,6 +590,11 @@
"resolved": "https://registry.npm.taobao.org/camelcase/download/camelcase-5.3.1.tgz",
"integrity": "sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA="
},
"caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
},
"chai": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz",
@@ -628,6 +680,12 @@
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
},
"circular-json": {
"version": "0.5.9",
"resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz",
"integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==",
"dev": true
},
"cliff": {
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/cliff/-/cliff-0.1.10.tgz",
@@ -791,6 +849,14 @@
"resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz",
"integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI="
},
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
"requires": {
"assert-plus": "^1.0.0"
}
},
"data-uri-to-buffer": {
"version": "3.0.1",
"resolved": "https://registry.npm.taobao.org/data-uri-to-buffer/download/data-uri-to-buffer-3.0.1.tgz",
@@ -922,6 +988,15 @@
"stream-shift": "^1.0.0"
}
},
"ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
"integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
"requires": {
"jsbn": "~0.1.0",
"safer-buffer": "^2.1.0"
}
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -1070,6 +1145,11 @@
"resolved": "https://registry.nlark.com/esutils/download/esutils-2.0.3.tgz",
"integrity": "sha1-dNLrTeC42hKTcRkQ1Qd1ubcQ72Q="
},
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
},
"extend-shallow": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
@@ -1078,11 +1158,26 @@
"is-extendable": "^0.1.0"
}
},
"extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g=="
},
"eyes": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz",
"integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A="
},
"fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
},
"fast-levenshtein": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
@@ -1127,6 +1222,11 @@
"resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz",
"integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg=="
},
"forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
"integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw=="
},
"form-data": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz",
@@ -1295,6 +1395,14 @@
"ftp": "^0.3.10"
}
},
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
"requires": {
"assert-plus": "^1.0.0"
}
},
"glob": {
"version": "7.1.6",
"resolved": "https://registry.npm.taobao.org/glob/download/glob-7.1.6.tgz",
@@ -1328,6 +1436,20 @@
"integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
"dev": true
},
"har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
"integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q=="
},
"har-validator": {
"version": "5.1.5",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
"integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
"requires": {
"ajv": "^6.12.3",
"har-schema": "^2.0.0"
}
},
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
@@ -1405,6 +1527,16 @@
"debug": "4"
}
},
"http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
"integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
"requires": {
"assert-plus": "^1.0.0",
"jsprim": "^1.2.2",
"sshpk": "^1.7.0"
}
},
"https-proxy-agent": {
"version": "5.0.0",
"resolved": "https://registry.npm.taobao.org/https-proxy-agent/download/https-proxy-agent-5.0.0.tgz?cache=0&sync_timestamp=1614740547969&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttps-proxy-agent%2Fdownload%2Fhttps-proxy-agent-5.0.0.tgz",
@@ -1581,6 +1713,11 @@
"has-symbols": "^1.0.1"
}
},
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@@ -1630,6 +1767,26 @@
"esprima": "^4.0.0"
}
},
"jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg=="
},
"json-schema": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
"integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="
},
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="
},
"jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
@@ -1638,6 +1795,17 @@
"graceful-fs": "^4.1.6"
}
},
"jsprim": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
"integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
"requires": {
"assert-plus": "1.0.0",
"extsprintf": "1.3.0",
"json-schema": "0.4.0",
"verror": "1.10.0"
}
},
"kareem": {
"version": "2.3.1",
"resolved": "https://registry.npm.taobao.org/kareem/download/kareem-2.3.1.tgz",
@@ -2013,6 +2181,172 @@
}
}
},
"mocha-parallel-tests": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/mocha-parallel-tests/-/mocha-parallel-tests-2.3.0.tgz",
"integrity": "sha512-GdU55VkOCXK2aBmjFzBE11RsSolA71WJppucU3BrTbMUpGIWnTidrje5Hvdr+hOolynEiv6fHWyoNT41mq4HkA==",
"dev": true,
"requires": {
"circular-json": "^0.5.9",
"debug": "^4.1.1",
"uuid": "^3.4.0",
"yargs": "^13.3.0"
},
"dependencies": {
"ansi-regex": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
"integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
"dev": true
},
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
}
},
"cliui": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
"integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
"dev": true,
"requires": {
"string-width": "^3.1.0",
"strip-ansi": "^5.2.0",
"wrap-ansi": "^5.1.0"
}
},
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dev": true,
"requires": {
"color-name": "1.1.3"
}
},
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
"dev": true
},
"emoji-regex": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
"integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
"dev": true
},
"find-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
"dev": true,
"requires": {
"locate-path": "^3.0.0"
}
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==",
"dev": true
},
"locate-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
"dev": true,
"requires": {
"p-locate": "^3.0.0",
"path-exists": "^3.0.0"
}
},
"p-locate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
"dev": true,
"requires": {
"p-limit": "^2.0.0"
}
},
"path-exists": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
"integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
"dev": true
},
"string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
"dev": true,
"requires": {
"emoji-regex": "^7.0.1",
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^5.1.0"
}
},
"strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
"dev": true,
"requires": {
"ansi-regex": "^4.1.0"
}
},
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
"dev": true
},
"wrap-ansi": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
"integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.0",
"string-width": "^3.0.0",
"strip-ansi": "^5.0.0"
}
},
"yargs": {
"version": "13.3.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
"integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
"dev": true,
"requires": {
"cliui": "^5.0.0",
"find-up": "^3.0.0",
"get-caller-file": "^2.0.1",
"require-directory": "^2.1.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^3.0.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^13.1.2"
}
},
"yargs-parser": {
"version": "13.1.2",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
"integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
"dev": true,
"requires": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
}
}
}
},
"moment": {
"version": "2.29.1",
"resolved": "https://registry.npm.taobao.org/moment/download/moment-2.29.1.tgz?cache=0&sync_timestamp=1601983423917&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmoment%2Fdownload%2Fmoment-2.29.1.tgz",
@@ -2320,6 +2654,11 @@
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
},
"oauth-sign": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
},
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -2505,6 +2844,11 @@
"through": "~2.3"
}
},
"performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
},
"picomatch": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
@@ -3025,6 +3369,55 @@
"resolved": "https://registry.npm.taobao.org/regexp-clone/download/regexp-clone-1.0.0.tgz",
"integrity": "sha1-Ii25Z2IydwViYLmSYmNUoEzpv2M="
},
"request": {
"version": "2.88.2",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
"integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
"requires": {
"aws-sign2": "~0.7.0",
"aws4": "^1.8.0",
"caseless": "~0.12.0",
"combined-stream": "~1.0.6",
"extend": "~3.0.2",
"forever-agent": "~0.6.1",
"form-data": "~2.3.2",
"har-validator": "~5.1.3",
"http-signature": "~1.2.0",
"is-typedarray": "~1.0.0",
"isstream": "~0.1.2",
"json-stringify-safe": "~5.0.1",
"mime-types": "~2.1.19",
"oauth-sign": "~0.9.0",
"performance-now": "^2.1.0",
"qs": "~6.5.2",
"safe-buffer": "^5.1.2",
"tough-cookie": "~2.5.0",
"tunnel-agent": "^0.6.0",
"uuid": "^3.3.2"
},
"dependencies": {
"form-data": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.6",
"mime-types": "^2.1.12"
}
},
"qs": {
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
"integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA=="
},
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
}
}
},
"request-promise": {
"version": "4.2.6",
"resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz",
@@ -3332,6 +3725,22 @@
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
"dev": true
},
"sshpk": {
"version": "1.17.0",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
"integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==",
"requires": {
"asn1": "~0.2.3",
"assert-plus": "^1.0.0",
"bcrypt-pbkdf": "^1.0.0",
"dashdash": "^1.12.0",
"ecc-jsbn": "~0.1.1",
"getpass": "^0.1.1",
"jsbn": "~0.1.0",
"safer-buffer": "^2.0.2",
"tweetnacl": "~0.14.0"
}
},
"stack-trace": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
@@ -3611,6 +4020,19 @@
"tslib": "^1.8.1"
}
},
"tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
"requires": {
"safe-buffer": "^5.0.1"
}
},
"tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA=="
},
"type-check": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
@@ -3624,6 +4046,14 @@
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
"integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g=="
},
"typegoose": {
"version": "5.9.1",
"resolved": "https://registry.npmjs.org/typegoose/-/typegoose-5.9.1.tgz",
"integrity": "sha512-D+vMhNyZeKBZHrmJFZwOodl3T9W2NOXY+hbnW/f1n60oEL8+L15eryFc9C6fAKrlnkgpui+kdQnNXsLwx2MgCw==",
"requires": {
"reflect-metadata": "^0.1.13"
}
},
"typescript": {
"version": "4.4.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz",
@@ -3653,6 +4083,14 @@
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
},
"uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
"requires": {
"punycode": "^2.1.0"
}
},
"urllib": {
"version": "2.37.1",
"resolved": "https://registry.npm.taobao.org/urllib/download/urllib-2.37.1.tgz?cache=0&sync_timestamp=1618453009809&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Furllib%2Fdownload%2Furllib-2.37.1.tgz",
@@ -3717,6 +4155,16 @@
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
},
"verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
"requires": {
"assert-plus": "^1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "^1.2.0"
}
},
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",

View File

@@ -4,7 +4,7 @@
"private": false,
"main": "./dist/app",
"scripts": {
"build": "tsc",
"build": "tsc && cp ./app/resource/privateKey ./dist/app/resource/privateKey && cp ./app/resource/publicKey ./dist/app/resource/publicKey ",
"start": "yarn run build && cd dist && node app",
"dev": "node tsrun.js",
"test": "./node_modules/mocha/bin/mocha -t 5000 -r ts-node/register ./test/*test.ts",

5
package-lock.json generated
View File

@@ -670,6 +670,11 @@
"resolved": "https://registry.npm.taobao.org/kareem/download/kareem-2.3.1.tgz",
"integrity": "sha1-3vEtnJQQF/q/sA+HOvlenJnhvoc="
},
"koa-is-json": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/koa-is-json/-/koa-is-json-1.0.0.tgz",
"integrity": "sha512-+97CtHAlWDx0ndt0J8y3P12EWLwTLMXIfMnYDev3wOTwH/RpBGMlfn4bDXlMEg1u73K6XRE9BbUp+5ZAYoRYWw=="
},
"lodash": {
"version": "4.17.20",
"resolved": "https://registry.npm.taobao.org/lodash/download/lodash-4.17.20.tgz?cache=0&sync_timestamp=1597336097104&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash%2Fdownload%2Flodash-4.17.20.tgz",

View File

@@ -11,6 +11,7 @@
"chinese-random-name": "^1.0.0",
"crc": "^3.8.0",
"csprng": "^0.1.2",
"koa-is-json": "^1.0.0",
"lodash": "^4.17.20",
"moment": "^2.27.0",
"mongoose": "^5.10.4",

View File

@@ -15,6 +15,8 @@ export const STATUS = {
ACCESS_BUSY: { code: 12, simStr: '您的点击过于频繁,服务器受不了了' },
ONLINE_USER_MAX: { code: 13, simStr: '服务器繁忙,请稍后再试' },
FUNCTION_CLOSE: { code: 14, simStr: '抱歉,该功能暂时关闭' },
TIMESTAMP_ERR: { code: 15, simStr: '请求时间参数错误' },
DUPLICATE_ACCESS: { code: 16, simStr: '随机请求参数重复' },
GLOBAL_ERR: { code: 1003, simStr: '服务器内部错误' },
UPDATE_INFO_ERR: {code: 1004, simStr: '热更新配置错误'},
// http请求

View File

@@ -35,6 +35,10 @@ export interface DicServerConst {
readonly CHECK_WORD: number;
// 是否可以支付
readonly CAN_PAY: number;
// 请求timestamp差距
readonly TIME_STAMP_OVER: number;
// 请求参数过期时间
readonly ACCESS_CODE_EXPIRE_TIME: number;
}
export const dicServerConst: DicServerConst = {} as DicServerConst;

117
shared/pubUtils/sysUtil.ts Normal file
View File

@@ -0,0 +1,117 @@
import { ENCRYPT_IV, ENCRYPT_KEY } from '../consts';
import { WhiteListModel } from '../db/RegionWhiteList';
const fs = require('fs');
const path = require('path');
import { aesDecrypt, aesEncrypt } from './util';
const crypto = require('crypto');
const isJSON = require('koa-is-json');
const privateKey = fs.readFileSync(path.resolve(__dirname, `../resource/privateKey`));
const publicKey = fs.readFileSync(path.resolve(__dirname, `../resource/publicKey`)); // 发推送加密的秘钥和privateKey不是一对
export async function checkWhiteList(env: string, ip: string, uid: number, serverId: number) {
if(ip) {
let result = await WhiteListModel.checkIp(env, ip);
if(!!result) return true;
}
if(uid && serverId) {
let result = await WhiteListModel.checkUid(env, serverId, uid);
if(!!result) return true;
}
return false
}
export class MsgEncrypt {
private k: string = ENCRYPT_KEY;
private v: string = ENCRYPT_IV;
private encodeK: string = '';
private encodeV: string = '';
constructor(data: { k?: string, v?: string, encodeK?: string, encodeV?: string }) {
if(data.k && data.v) {
this.encodeAndSetKv(data.k, data.v);
}
if(data.encodeK && data.encodeV) {
this.decodeAndSetKv(data.encodeK, data.encodeV);
}
}
public decryptMsg(data: string) {
if(!data) return false
try {
const decodeStr = aesDecrypt(data, this.k, this.v);
console.log('decoded str:', decodeStr);
let body = JSON.parse(decodeStr);
return body
} catch(e) {
console.error(e);
return false;
}
}
public encryptMsg(json: Object) {
if(!isJSON(json)) return false;
try {
const encodeStr = aesEncrypt(JSON.stringify(json), this.k, this.v);
// console.log('encode str:', encodeStr);
return encodeStr;
} catch(e) {
console.error(e);
return false;
}
}
public decodeAndSetKv(requestK: string, requestV: string) {
if(requestK) {
this.encodeK = requestK;
this.k = this.privateDecrypt(Buffer.from(requestK, 'base64'));
}
if(requestV) {
this.encodeV = requestV;
this.v = this.privateDecrypt(Buffer.from(requestV, 'base64'));
}
return this.getKv();
}
public getKv() {
return { aesKey: this.k, aesIV: this.v }
}
public getEncodeKv() {
return { aesKey: this.encodeK, aesIV: this.encodeV }
}
private privateDecrypt(encryptMsg: Buffer) {
const decryptMsg = crypto.privateDecrypt(
{ key: privateKey, padding: crypto.constants.RSA_PKCS1_PADDING },
encryptMsg
);
return decryptMsg.toString();
}
private getRsaEncodedData(original: string) {
const encryptMsg = crypto.publicEncrypt(
{ key: publicKey, padding: crypto.constants.RSA_PKCS1_PADDING },
Buffer.from(original)
);
return encryptMsg.toString('base64');
}
private encodeAndSetKv(k: string, v: string) {
if(k) {
this.k = k;
this.encodeK = this.getRsaEncodedData(k);
}
if(v) {
this.v = v;
this.encodeV = this.getRsaEncodedData(v);
}
}
}

View File

@@ -10,7 +10,6 @@ import { ABI_STAGE, REFRESH_TIME, ROBOT_SYS_TYPE, ITEM_CHANGE_REASON, WAR_TYPE,
import { findIndex } from 'underscore';
import { getZeroPointD } from './timeUtil';
import { Floor } from '../domain/activityField/gachaField';
import { WhiteListModel } from '../db/RegionWhiteList';
import { RewardInter } from './interface';
import { gameData } from './data';
const randomName = require("chinese-random-name");
@@ -621,17 +620,6 @@ export function splitString(dataString: string, key: string) {
return numberArray;
}
export async function checkWhiteList(env: string, ip: string, uid: number, serverId: number) {
if(ip) {
let result = await WhiteListModel.checkIp(env, ip);
if(!!result) return true;
}
if(uid && serverId) {
let result = await WhiteListModel.checkUid(env, serverId, uid);
if(!!result) return true;
}
return false
}
export function isTimestamp(time: number, len = 10) {
if(!isNumber(time)) return false;

View File

@@ -16,6 +16,8 @@
{ "id": 8, "desc": "捐赠", "route": "guild.donateHandler.donate", "param": {}, "interval": 200 },
{ "id": 9, "desc": "碾压镇念塔", "route": "battle.towerBattleHandler.skipTower", "param": {}, "interval": 200 }
],
"TIME_STAMP_OVER": 900000,
"ACCESS_CODE_EXPIRE_TIME": 900000,
"DEBUG_PAY": 0,
"DEBUG_TIME": 1,
"CHECK_WORD": 1,

View File

@@ -0,0 +1,6 @@
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDiU143FYs5+uJlIn/AK6gKhOEl
WydR/7OJ1MUSWFJz9yL/acIyNBQ4Ji/0adDaIB01pQ9eqCYFP0Z9SgGMcpST/ejU
LEUbjls7GTwutxoVVe9PUDBkRY601RVAEjXaZmWfZZ7028uWrqfJmeEo3voKhscO
/vCOKII2TM1xC+FMGwIDAQAB
-----END PUBLIC KEY-----

View File

@@ -1,7 +1,7 @@
import { STATUS } from '@consts';
import { ServerlistModel } from '@db/Serverlist';
import { nowSeconds } from 'app/pubUtils/timeUtil';
import { checkWhiteList } from 'app/pubUtils/util';
import { checkWhiteList } from 'app/pubUtils/sysUtil';
module.exports = () => {
return async function checkMainten(ctx, next) {

View File

@@ -1,34 +1,6 @@
import { ENCRYPT_KEY, ENCRYPT_IV } from '@consts';
import { genCode } from 'app/pubUtils/util';
import { MsgEncrypt } from "app/pubUtils/sysUtil";
import { Context } from 'egg';
const crypto = require('crypto');
const isJSON = require('koa-is-json');
import fs = require('fs');
import path = require('path');
const privateKey = fs.readFileSync(path.resolve(__dirname, `../resource/privateKey`));
function aesEncrypt(data, key, iv) {
const cipher = crypto.createCipheriv('aes-192-cbc', key, iv);
let crypted = cipher.update(data, 'utf8', 'hex');
crypted += cipher.final('hex');
return crypted;
}
function aesDecrypt(data, key, iv) {
const decipher = crypto.createDecipheriv('aes-192-cbc', key, iv);
let decrypted = decipher.update(data, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
function privateDecrypt(encryptMsg) {
const decryptMsg = crypto.privateDecrypt(
{ key: privateKey, padding: crypto.constants.RSA_PKCS1_PADDING },
encryptMsg
);
return decryptMsg;
}
module.exports = options => {
return async function parmsDecode(ctx: Context, next) {
@@ -42,16 +14,7 @@ module.exports = options => {
}
if (options.threshold && ctx.length < options.threshold) return;
const reqBody = ctx.request.body;
const reqHeader = ctx.request.header;
const aesKey = reqHeader['k'] ? privateDecrypt(new Buffer(reqHeader['k'], 'base64')) : ENCRYPT_KEY;
const aesIV = reqHeader['v'] ? privateDecrypt(new Buffer(reqHeader['v'], 'base64')) : ENCRYPT_IV;
if (isJSON(reqBody)) {
const encodeStr = aesEncrypt(JSON.stringify(reqBody), aesKey, aesIV);
console.log(`encoded str: ${encodeStr}`);
}
console.log(ctx.app.config.decodeParm)
if(ctx.app.config.decodeParm == false) {
@@ -59,13 +22,18 @@ module.exports = options => {
return;
}
if (!reqBody.data) return;
const decodeStr = aesDecrypt(reqBody.data, aesKey, aesIV);
ctx.logger.debug('decoded str:', decodeStr);
let msgEncrypt = new MsgEncrypt({ encodeK: reqHeader['k'], encodeV: reqHeader['v'] });
const { aesKey, aesIV } = msgEncrypt.getKv();
console.log(`encode str ${msgEncrypt.encryptMsg(reqBody)}`);
try {
ctx.request.body = JSON.parse(decodeStr);
let decryptResult = msgEncrypt.decryptMsg(reqBody.data);
if(!decryptResult) throw new Error('params parse err');
ctx.request.body = decryptResult;
console.log('req body', ctx.request.body);
ctx.service.utils.log('INFO', `[${ctx.request.url}] [${ctx.logcode}] request: ${JSON.stringify(ctx.request.body)}`)
} catch (e) {
@@ -82,11 +50,12 @@ module.exports = options => {
}
const resBody = ctx.body;
console.log('return value:', JSON.stringify(resBody));
if (isJSON(resBody)) {
ctx.body = { result: aesEncrypt(JSON.stringify(resBody), aesKey, aesIV) };
let resBodyWithEncrypt = msgEncrypt.encryptMsg(resBody);
if (resBodyWithEncrypt) {
ctx.body = { result: resBodyWithEncrypt, aesKey, aesIV };
ctx.service.utils.log('INFO', `[${ctx.request.url}] [${ctx.logcode}] res: ${JSON.stringify(resBody)}`)
} else {
ctx.body = { result: aesEncrypt(JSON.stringify({ status: 3, data: 'internal err' }), aesKey, aesIV) };
ctx.body = { result: msgEncrypt.encryptMsg({ status: 3, data: 'internal err' }), aesKey, aesIV };
ctx.service.utils.log('ERROR', `[${ctx.request.url}] [${ctx.logcode}] res: ${resBody}`)
}
};