From 469e393f5ee2c14b66e5bb0f459cdf43d5b916d0 Mon Sep 17 00:00:00 2001 From: luying Date: Thu, 16 Jun 2022 19:14:05 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=A0=E5=AF=86=EF=BC=9A=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=8A=A0=E5=AF=86=E8=A7=A3=E5=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game-server/app.ts | 1 - .../activity/handler/activityHandler.ts | 2 +- .../app/servers/connector/filter/global.ts | 297 ++++++++---- game-server/app/services/gmService.ts | 1 - game-server/app/services/pushService.ts | 32 +- game-server/app/services/redisService.ts | 2 + game-server/package-lock.json | 448 ++++++++++++++++++ game-server/package.json | 2 +- package-lock.json | 5 + package.json | 1 + shared/consts/statusCode.ts | 2 + shared/pubUtils/dictionary/DicServerConst.ts | 4 + shared/pubUtils/sysUtil.ts | 117 +++++ shared/pubUtils/util.ts | 12 - shared/resource/jsons/server_const.json | 2 + shared/resource/publicKey | 6 + web-server/app/middleware/checkMainten.ts | 2 +- web-server/app/middleware/parmsDecode.ts | 59 +-- 18 files changed, 833 insertions(+), 162 deletions(-) create mode 100644 shared/pubUtils/sysUtil.ts create mode 100644 shared/resource/publicKey diff --git a/game-server/app.ts b/game-server/app.ts index 28b20cc10..bb28a96ac 100644 --- a/game-server/app.ts +++ b/game-server/app.ts @@ -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); }) diff --git a/game-server/app/servers/activity/handler/activityHandler.ts b/game-server/app/servers/activity/handler/activityHandler.ts index bd11d99b4..6f5a082e1 100644 --- a/game-server/app/servers/activity/handler/activityHandler.ts +++ b/game-server/app/servers/activity/handler/activityHandler.ts @@ -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'; diff --git a/game-server/app/servers/connector/filter/global.ts b/game-server/app/servers/connector/filter/global.ts index 40cb772d3..009648b70 100644 --- a/game-server/app/servers/connector/filter/global.ts +++ b/game-server/app/servers/connector/filter/global.ts @@ -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(); -}; +class Filter { + private app: Application; + private accessTime = new Map(); -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(); + 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(); - 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); -}; \ No newline at end of file + await redis.setAsync(`cs: ${cs}`, ''); + await redis.expireAsync(`cs: ${cs}`, gameData.serverConst.ACCESS_CODE_EXPIRE_TIME/1000); + return true; + } +} \ No newline at end of file diff --git a/game-server/app/services/gmService.ts b/game-server/app/services/gmService.ts index ce5af8e7a..a2ee72213 100644 --- a/game-server/app/services/gmService.ts +++ b/game-server/app/services/gmService.ts @@ -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"; // —————————————— 跑马灯 —————————————— // diff --git a/game-server/app/services/pushService.ts b/game-server/app/services/pushService.ts index 073b19c50..abd174dee 100644 --- a/game-server/app/services/pushService.ts +++ b/game-server/app/services/pushService.ts @@ -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); } -} \ No newline at end of file +} + +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 } +} diff --git a/game-server/app/services/redisService.ts b/game-server/app/services/redisService.ts index 9ba274b65..ed39804e1 100644 --- a/game-server/app/services/redisService.ts +++ b/game-server/app/services/redisService.ts @@ -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), diff --git a/game-server/package-lock.json b/game-server/package-lock.json index 2434de1df..c6dcd7296 100644 --- a/game-server/package-lock.json +++ b/game-server/package-lock.json @@ -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", diff --git a/game-server/package.json b/game-server/package.json index 2582e10e7..efa3c4bfb 100644 --- a/game-server/package.json +++ b/game-server/package.json @@ -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", diff --git a/package-lock.json b/package-lock.json index 6ff43b4cf..f5b94d554 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index 12bfa76fe..dea3bcead 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/shared/consts/statusCode.ts b/shared/consts/statusCode.ts index a07729666..183812217 100644 --- a/shared/consts/statusCode.ts +++ b/shared/consts/statusCode.ts @@ -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请求 diff --git a/shared/pubUtils/dictionary/DicServerConst.ts b/shared/pubUtils/dictionary/DicServerConst.ts index 2bbd17f91..8d9d2ebf3 100644 --- a/shared/pubUtils/dictionary/DicServerConst.ts +++ b/shared/pubUtils/dictionary/DicServerConst.ts @@ -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; diff --git a/shared/pubUtils/sysUtil.ts b/shared/pubUtils/sysUtil.ts new file mode 100644 index 000000000..1df0bc9af --- /dev/null +++ b/shared/pubUtils/sysUtil.ts @@ -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); + } + } +} + diff --git a/shared/pubUtils/util.ts b/shared/pubUtils/util.ts index 21ba525e6..28fc28acc 100644 --- a/shared/pubUtils/util.ts +++ b/shared/pubUtils/util.ts @@ -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; diff --git a/shared/resource/jsons/server_const.json b/shared/resource/jsons/server_const.json index 6d3dcb500..ed329d3f1 100644 --- a/shared/resource/jsons/server_const.json +++ b/shared/resource/jsons/server_const.json @@ -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, diff --git a/shared/resource/publicKey b/shared/resource/publicKey new file mode 100644 index 000000000..675bfe852 --- /dev/null +++ b/shared/resource/publicKey @@ -0,0 +1,6 @@ +-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDiU143FYs5+uJlIn/AK6gKhOEl +WydR/7OJ1MUSWFJz9yL/acIyNBQ4Ji/0adDaIB01pQ9eqCYFP0Z9SgGMcpST/ejU +LEUbjls7GTwutxoVVe9PUDBkRY601RVAEjXaZmWfZZ7028uWrqfJmeEo3voKhscO +/vCOKII2TM1xC+FMGwIDAQAB +-----END PUBLIC KEY----- diff --git a/web-server/app/middleware/checkMainten.ts b/web-server/app/middleware/checkMainten.ts index 6954f2bbd..ac6aaadae 100644 --- a/web-server/app/middleware/checkMainten.ts +++ b/web-server/app/middleware/checkMainten.ts @@ -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) { diff --git a/web-server/app/middleware/parmsDecode.ts b/web-server/app/middleware/parmsDecode.ts index baaf87e63..78c64ac63 100644 --- a/web-server/app/middleware/parmsDecode.ts +++ b/web-server/app/middleware/parmsDecode.ts @@ -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}`) } };