|
|
'use strict';
|
|
|
|
|
|
const _ = require('lodash');
|
|
|
const logger = global.yoho.logger;
|
|
|
const ip = require('./rules/ip-list');
|
|
|
const userAgent = require('./rules/useragent');
|
|
|
const qpsLimiter = require('./rules/qps-limit');
|
|
|
const fakerLimiter = require('./rules/faker-limit');
|
|
|
const captchaPolicy = require('./policies/captcha');
|
|
|
const reporterPolicy = require('./policies/reporter');
|
|
|
|
|
|
const IP_WHITE_LIST = [
|
|
|
// '106.38.38.146',
|
|
|
// '218.94.75.58'
|
|
|
];
|
|
|
|
|
|
const limiter = (rule, policy, context) => {
|
|
|
return rule(context, policy);
|
|
|
};
|
|
|
|
|
|
module.exports = (req, res, next) => {
|
|
|
let remoteIp = req.get('X-Forwarded-For') || req.connection.remoteAddress;
|
|
|
logger.debug('request remote ip: ', remoteIp);
|
|
|
|
|
|
if (remoteIp.indexOf(',') > 0) {
|
|
|
let arr = remoteIp.split(',');
|
|
|
|
|
|
remoteIp = arr[0];
|
|
|
}
|
|
|
|
|
|
const excluded = _.includes(IP_WHITE_LIST, remoteIp);
|
|
|
const enabled = !_.get(req.app.locals, 'wap.sys.noLimiter');
|
|
|
|
|
|
// 判断获取remoteIp成功,并且开关未关闭
|
|
|
if (enabled && remoteIp && !excluded) {
|
|
|
const context = {
|
|
|
req: req,
|
|
|
res: res,
|
|
|
next: next,
|
|
|
remoteIp: remoteIp
|
|
|
};
|
|
|
|
|
|
Promise.all([
|
|
|
limiter(userAgent, captchaPolicy, context),
|
|
|
limiter(ip, captchaPolicy, context),
|
|
|
limiter(qpsLimiter, captchaPolicy, context),
|
|
|
//limiter(fakerLimiter, reporterPolicy, context)
|
|
|
]).then((results) => {
|
|
|
let allPass = true, exclusion = false, policy = null;
|
|
|
|
|
|
logger.debug('limiter result: ' + JSON.stringify(results));
|
|
|
|
|
|
_.forEach(results, (result) => {
|
|
|
if (typeof result === 'object' && !exclusion) {
|
|
|
exclusion = result.exclusion;
|
|
|
}
|
|
|
|
|
|
if (!excluded && typeof result === 'function') {
|
|
|
allPass = false;
|
|
|
}
|
|
|
|
|
|
if (typeof result === 'function') {
|
|
|
policy = result;
|
|
|
}
|
|
|
});
|
|
|
|
|
|
if (exclusion) {
|
|
|
return next();
|
|
|
} else if (!allPass && policy) {
|
|
|
policy(req, res, next);
|
|
|
} else {
|
|
|
return next();
|
|
|
}
|
|
|
|
|
|
}).catch((err) => {
|
|
|
logger.error(err);
|
|
|
return next();
|
|
|
});
|
|
|
} else {
|
|
|
return next();
|
|
|
}
|
|
|
}; |
...
|
...
|
|