防护:接口访问限制

This commit is contained in:
luying
2022-01-08 18:15:25 +08:00
parent 0f8a4a946e
commit e793e8bc94
6 changed files with 45 additions and 24 deletions
+2 -1
View File
@@ -169,7 +169,8 @@ app.configure(ALL_ENVS, 'activity', function () {
function errorHandler(err: Error, msg: any, resp: any, function errorHandler(err: Error, msg: any, resp: any,
session: FrontendOrBackendSession, cb: HandlerCallback) { session: FrontendOrBackendSession, cb: HandlerCallback) {
const errCode = genCode(10); const errCode = genCode(10);
errlogger.error(`${pinus.app.serverId} error handler \n msg[${JSON.stringify(msg)}] \n resp[${JSON.stringify(resp)}] \n sessionId:${JSON.stringify(session.export())} \n error 【${errCode}】 stack: ${err.stack}`); if(err.message != 'globalFilter')
errlogger.error(`${pinus.app.serverId} error handler \n msg[${JSON.stringify(msg)}] \n resp[${JSON.stringify(resp)}] \n sessionId:${JSON.stringify(session.export())} \n error 【${errCode}】 stack: ${err.stack}`);
if (!resp) { if (!resp) {
resp = resResult(STATUS.GLOBAL_ERR, { errCode, stack: err.stack }); resp = resResult(STATUS.GLOBAL_ERR, { errCode, stack: err.stack });
@@ -3,12 +3,12 @@ import {Application, RouteRecord, FrontendOrBackendSession, HandlerCallback, pin
import { refresh } from '../../../services/refreshService'; import { refresh } from '../../../services/refreshService';
import { checkPrivateChat, checkGuildChat, checkOtherChat, checkRoleName, checkGuildName } from "../../../services/sdkService"; import { checkPrivateChat, checkGuildChat, checkOtherChat, checkRoleName, checkGuildName } from "../../../services/sdkService";
import { resResult, checkWhiteList, genCode } from "../../../pubUtils/util"; import { resResult, checkWhiteList, genCode } from "../../../pubUtils/util";
import { ACCESS_FREQUENCY, BLOCK_TYPE, CHANNEL_PREFIX, MSG_TYPE, STATUS } from "../../../consts"; import { BLOCK_TYPE, CHANNEL_PREFIX, MSG_TYPE, STATUS } from "../../../consts";
import { UserModel } from "../../../db/User";
import { SERVER_DEBUG_MODE } from "../../../pubUtils/dicParam"; import { SERVER_DEBUG_MODE } from "../../../pubUtils/dicParam";
import { nowSeconds } from "../../../pubUtils/timeUtil"; import { nowSeconds } from "../../../pubUtils/timeUtil";
import { getServerMainten } from "../../../services/gmService"; import { getServerMainten } from "../../../services/gmService";
// import { errlogger } from "../../../util/logger"; import { errlogger } from "../../../util/logger";
import { gameData } from "../../../pubUtils/data";
export function globalFilter(app: Application) { export function globalFilter(app: Application) {
return new Filter(app); return new Filter(app);
} }
@@ -18,6 +18,32 @@ var Filter = function(this: any, app: Application) {
this.accessTime = new Map<string, number>(); this.accessTime = new Map<string, number>();
}; };
Filter.prototype.checkFrequency = function(route: string, roleId: string) {
if(gameData.serverConst.PROTECT_API.indexOf(route) == -1) {
return true;
}
let keyOfRouteWithUser = `${route}_${roleId}`;
if(this.accessTime && this.accessTime.has(keyOfRouteWithUser)) {
console.log(this.accessTime.get(keyOfRouteWithUser) - Date.now());
if(Date.now() - this.accessTime.get(keyOfRouteWithUser) < gameData.serverConst.PROTECT_API_INTERVAL) {
errlogger.error(`${keyOfRouteWithUser} 间隔时间小于${gameData.serverConst.PROTECT_API_INTERVAL}ms,为 ${Date.now() - this.accessTime.get(keyOfRouteWithUser)}`);
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) { Filter.prototype.before = async function (routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, next: HandlerCallback) {
const serverId: number = session.get('serverId'); const serverId: number = session.get('serverId');
const sid: string = session.get('sid'); const sid: string = session.get('sid');
@@ -28,18 +54,15 @@ Filter.prototype.before = async function (routeRecord: RouteRecord, msg: any, se
let guildCode = session.get('guildCode'); let guildCode = session.get('guildCode');
let blockType = session.get('blockType'); let blockType = session.get('blockType');
// 访问频率控制 // 访问频率控制
let keyOfRouteWithUser = `${routeRecord.route}_${roleId}`; if(!this.checkFrequency(routeRecord.route, roleId)) {
if(this.accessTime && this.accessTime.has(keyOfRouteWithUser)) { return next(new Error('globalFilter'), resResult(STATUS.ACCESS_BUSY));
console.log(this.accessTime.get(keyOfRouteWithUser) - Date.now());
if(Date.now() - this.accessTime.get(keyOfRouteWithUser) < ACCESS_FREQUENCY) {
// errlogger.error(`${keyOfRouteWithUser} 间隔时间小于${ACCESS_FREQUENCY}ms,为 ${Date.now() - this.accessTime.get(keyOfRouteWithUser)}`);
// return next(new Error(), resResult(STATUS.ACCESS_BUSY));
}
} }
if(!this.accessTime) this.accessTime = new Map<string, number>(); if(!this.checkFunction(routeRecord.route)) {
this.accessTime.set(keyOfRouteWithUser, Date.now()); return next(new Error('globalFilter'), resResult(STATUS.FUNCTION_CLOSE));
}
// 玩家屏蔽 // 玩家屏蔽
if(blockType == BLOCK_TYPE.BLOCK) return next(new Error(), resResult(STATUS.BLOCKED)); if(blockType == BLOCK_TYPE.BLOCK) return next(new Error('globalFilter'), resResult(STATUS.BLOCKED));
if(blockType == BLOCK_TYPE.BAN) { if(blockType == BLOCK_TYPE.BAN) {
if([ if([
'chat.chatHandler.sendPrivateMessage', 'chat.chatHandler.sendPrivateMessage',
@@ -48,7 +71,7 @@ Filter.prototype.before = async function (routeRecord: RouteRecord, msg: any, se
'guild.guildHandler.sendMail', 'guild.guildHandler.sendMail',
'guild.guildHandler.setGuildInfo', 'guild.guildHandler.setGuildInfo',
].indexOf(routeRecord.route) != -1) { ].indexOf(routeRecord.route) != -1) {
return next(new Error(), resResult(STATUS.BANNED)); return next(new Error('globalFilter'), resResult(STATUS.BANNED));
} }
} }
@@ -63,7 +86,7 @@ Filter.prototype.before = async function (routeRecord: RouteRecord, msg: any, se
if(isWhiteList) return next(null); if(isWhiteList) return next(null);
pinus.app.get('channelService').pushMessageByUids('onServerMaintenance', resResult(STATUS.SERVER_MAINTENANCE), [{ uid: roleId, sid }]); pinus.app.get('channelService').pushMessageByUids('onServerMaintenance', resResult(STATUS.SERVER_MAINTENANCE), [{ uid: roleId, sid }]);
return next(new Error(), resResult(STATUS.SERVER_MAINTENANCE)); return next(new Error('globalFilter'), resResult(STATUS.SERVER_MAINTENANCE));
} }
} }
@@ -123,7 +146,7 @@ Filter.prototype.before = async function (routeRecord: RouteRecord, msg: any, se
} }
} }
if(hasBlockWords) return next(new Error(), resResult(STATUS.BLOCK_WORDS)); if(hasBlockWords) return next(new Error('globalFilter'), resResult(STATUS.BLOCK_WORDS));
next(null); next(null);
}; };
-2
View File
@@ -25,8 +25,6 @@ export const REF_CIRCLE_MAIL_TIME = 3; // 统一一天刷新定期邮件时间
export const PUSH_BATCH = 100; // 推送分批人数 export const PUSH_BATCH = 100; // 推送分批人数
export const PUSH_INTERVAL = 5 * 1000; // 分批时间,5秒一批 export const PUSH_INTERVAL = 5 * 1000; // 分批时间,5秒一批
export const ACCESS_FREQUENCY = 500; // 玩家访问频率,一个玩家一个接口间隔时间 单位ms
export enum TIME_OUTPUT_TYPE { export enum TIME_OUTPUT_TYPE {
DATE = 1, DATE = 1,
STAMP_10 = 2, STAMP_10 = 2,
+1
View File
@@ -14,6 +14,7 @@ export const STATUS = {
BANNED: { code: 11, simStr: '您已被禁言' }, BANNED: { code: 11, simStr: '您已被禁言' },
ACCESS_BUSY: { code: 12, simStr: '您的操作过于繁忙' }, ACCESS_BUSY: { code: 12, simStr: '您的操作过于繁忙' },
ONLINE_USER_MAX: { code: 13, simStr: '服务器繁忙,请稍后再试' }, ONLINE_USER_MAX: { code: 13, simStr: '服务器繁忙,请稍后再试' },
FUNCTION_CLOSE: { code: 14, simStr: '抱歉,该功能暂时关闭' },
GLOBAL_ERR: { code: 1003, simStr: '服务器内部错误' }, GLOBAL_ERR: { code: 1003, simStr: '服务器内部错误' },
// http请求 // http请求
REQUEST_TIME_OUT: { code: 2000, simStr: '请求超时' }, REQUEST_TIME_OUT: { code: 2000, simStr: '请求超时' },
+1 -1
View File
@@ -7,7 +7,7 @@ export interface DicServerConst {
readonly PROTECT_API_INTERVAL: number; readonly PROTECT_API_INTERVAL: number;
// 保护的接口 // 保护的接口
readonly PROTECT_API: string[]; readonly PROTECT_API: string[];
// 这些api功能关闭 // 某些api功能关闭
readonly API_IS_CLOSE: number; readonly API_IS_CLOSE: number;
// 关闭的接口 // 关闭的接口
readonly CLOSE_APIS: string[]; readonly CLOSE_APIS: string[];
+2 -4
View File
@@ -5,10 +5,8 @@
"chat.chatHandler.sendPrivateMessage", "chat.chatHandler.sendPrivateMessage",
"battle.barrageHandler.sendBarrage" "battle.barrageHandler.sendBarrage"
], ],
"API_IS_CLOSE": 1, "API_IS_CLOSE": 0,
"CLOSE_APIS": [ "CLOSE_APIS": [],
"chat.chatHandler.sendGroupMessage"
],
"CLOSE_LOGIN": 0, "CLOSE_LOGIN": 0,
"CLOSE_LOGIN_WHEN_ONLINE_MAX": 1, "CLOSE_LOGIN_WHEN_ONLINE_MAX": 1,
"MAX_ONLINE_USER_COUNT": 5000 "MAX_ONLINE_USER_COUNT": 5000