'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 asynchronous = require('./rules/asynchronous'); // const fakerLimiter = require('./rules/faker-limit'); const captchaPolicy = require('./policies/captcha'); // const reporterPolicy = require('./policies/reporter'); const IP_WHITE_LIST = [ '106.38.38.146', '106.38.38.147', '106.39.86.227', '218.94.75.58', '218.94.75.50', '218.94.77.166' ]; const PATH_WHITE_LIST = [ '/3party/check', '/passport/images.png', '/passport/cert/headerTip', '/common/getbanner', '/common/suggestfeedback', '/product/search/history', '/product/search/suggest' ]; const limiter = (rule, policy, context) => { return rule(context, policy); }; module.exports = (req, res, next) => { let remoteIp = req.get('X-Forwarded-For') || req.get('X-Real-IP') || ''; if (remoteIp.indexOf(',') > 0) { let arr = remoteIp.split(','); remoteIp = arr[arr.length - 1]; } remoteIp = _.trim(remoteIp); if (_.startsWith(remoteIp, '10.66.')) { remoteIp = req.get('X-Real-IP'); } // 排除条件:ip白名单/路径白名单/异步请求/登录用户 const excluded = _.includes(IP_WHITE_LIST, remoteIp) || _.includes(PATH_WHITE_LIST, req.path) || req.xhr || !_.isEmpty(_.get(req, 'user.uid')); const enabled = !_.get(req.app.locals, 'pc.sys.noLimiter'); logger.debug(`request remote ip: ${remoteIp}; excluded: ${excluded}; enabled: ${enabled}`); // 判断获取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(asynchronous, 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 (typeof result === 'function') { allPass = false; 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(); } };