Authored by 郝肖肖

'limit'

@@ -9,6 +9,13 @@ const cache = global.yoho.cache.master; @@ -9,6 +9,13 @@ const cache = global.yoho.cache.master;
9 const helpers = global.yoho.helpers; 9 const helpers = global.yoho.helpers;
10 const pathToRegexp = require('path-to-regexp'); 10 const pathToRegexp = require('path-to-regexp');
11 11
  12 +const statusCode = {
  13 + code: 4403,
  14 + date: {},
  15 + message: '亲,您的访问次数过多,请稍后再试哦...'
  16 +};
  17 +
  18 +const INVALIDTIME = 3600 * 24; // 24h
12 const IP_WHITE_LIST = [ 19 const IP_WHITE_LIST = [
13 '106.38.38.146', 20 '106.38.38.146',
14 '106.38.38.147', 21 '106.38.38.147',
@@ -18,17 +25,33 @@ const IP_WHITE_LIST = [ @@ -18,17 +25,33 @@ const IP_WHITE_LIST = [
18 '218.94.77.166' 25 '218.94.77.166'
19 ]; 26 ];
20 27
  28 +const _jumpUrl = (req, res, next, result) => {
  29 + if (result.code === 4403) {
  30 + if (req.xhr) {
  31 + res.set({
  32 + 'Cache-Control': 'no-cache',
  33 + Pragma: 'no-cache',
  34 + Expires: (new Date(1900, 0, 1, 0, 0, 0, 0)).toUTCString()
  35 + });
  36 + return res.status(403).json(result);
  37 + }
  38 + return res.redirect(`${result.data.url}&refer=${req.originalUrl}`);
  39 + }
  40 +
  41 + return next();
  42 +};
  43 +
21 module.exports = () => { 44 module.exports = () => {
22 return (req, res, next) => { 45 return (req, res, next) => {
23 let ip = _.get(req.yoho, 'clientIp', ''); 46 let ip = _.get(req.yoho, 'clientIp', '');
24 let path = req.path || ''; 47 let path = req.path || '';
25 - let router = {};  
26 let risks = _.get(req.app.locals.wap, 'json.risk', []); 48 let risks = _.get(req.app.locals.wap, 'json.risk', []);
27 49
28 if (_.isEmpty(path) || _.isEmpty(risks) || IP_WHITE_LIST.indexOf(ip) > -1) { 50 if (_.isEmpty(path) || _.isEmpty(risks) || IP_WHITE_LIST.indexOf(ip) > -1) {
29 return next(); 51 return next();
30 } 52 }
31 53
  54 + let router = {};
32 _.isArray(risks) && risks.some(item => { 55 _.isArray(risks) && risks.some(item => {
33 if (item.state === 'off') { 56 if (item.state === 'off') {
34 return false; 57 return false;
@@ -52,47 +75,42 @@ module.exports = () => { @@ -52,47 +75,42 @@ module.exports = () => {
52 return next(); 75 return next();
53 } 76 }
54 77
55 - let key = `wap:risk:${_.trim(path, '/').replace(/\//g, ':')}:${ip}`; 78 + let keyPath = `${_.trim(path, '/').replace(/\//g, ':')}:${ip}`;
  79 + let limitKey = `wap:risk:limit:${keyPath}`;
  80 + let configKey = `wap:risk:${keyPath}`;
56 let checkUrl = helpers.urlFormat('/3party/check', { 81 let checkUrl = helpers.urlFormat('/3party/check', {
57 - pid: key 82 + pid: limitKey
58 }); 83 });
59 84
60 - return cache.getAsync(key).then(inter => {  
61 - if (typeof inter === 'undefined') {  
62 - return cache.setAsync(key, 1, router.interval || 300); 85 + return Promise.all([
  86 + cache.getAsync(limitKey),
  87 + cache.getAsync(configKey),
  88 + ]).then(inters => {
  89 + if (inters[0]) {
  90 + return Object.assign({}, statusCode, {data: {url: checkUrl}});
63 } 91 }
64 92
65 - inter = parseInt(`0${inter}`, 10);  
66 -  
67 - if (inter <= router.requests) {  
68 - return cache.incrAsync(key, 1); 93 + if (typeof inters[1] === 'undefined') {
  94 + cache.setAsync(configKey, 1, router.interval || 300);
  95 + return Object.assign({}, statusCode, {code: 200, message: ''});
69 } 96 }
70 97
71 - return inter;  
72 - }).then(inter => {  
73 - if (inter === true) { // cache set OR incr  
74 - return next(); 98 + inters[1] = parseInt(`0${inters[1]}`, 10);
  99 + if (inters[1] <= router.requests) {
  100 + router = [];
  101 + cache.incrAsync(configKey, 1);
  102 + return Object.assign({}, statusCode, {code: 200, message: ''});
75 } 103 }
76 104
77 - if (inter > router.requests) {  
78 - if (req.xhr) {  
79 - res.set({  
80 - 'Cache-Control': 'no-cache',  
81 - Pragma: 'no-cache',  
82 - Expires: (new Date(1900, 0, 1, 0, 0, 0, 0)).toUTCString() 105 + return Promise.all([
  106 + cache.setAsync(limitKey, 1, INVALIDTIME),
  107 + cache.delAsync(configKey)
  108 + ]).then(() => {
  109 + return Object.assign({}, statusCode, {data: {url: checkUrl}});
83 }); 110 });
84 - return res.status(403).json({  
85 - code: 4403,  
86 - date: {url: checkUrl},  
87 - message: '亲,您的访问次数过多,请稍后再试哦...'  
88 - });  
89 - }  
90 -  
91 - return res.redirect(`${checkUrl}&refer=${req.originalUrl}`);  
92 - }  
93 -  
94 - return next();  
95 - }).catch((e) => { 111 + }).then(result => {
  112 + return _jumpUrl(req, res, next, result);
  113 + }).catch(e => {
96 console.log(`risk => path: ${path}, err: ${e.message}`); 114 console.log(`risk => path: ${path}, err: ${e.message}`);
97 return next(); 115 return next();
98 }); 116 });