Merge branch 'master' into gray
Showing
24 changed files
with
450 additions
and
17 deletions
@@ -51,6 +51,11 @@ app.set('etag', false); | @@ -51,6 +51,11 @@ app.set('etag', false); | ||
51 | 51 | ||
52 | app.enable('trust proxy'); | 52 | app.enable('trust proxy'); |
53 | 53 | ||
54 | +// 请求限制中间件 | ||
55 | +if (!app.locals.devEnv) { | ||
56 | + app.use(require('./doraemon/middleware/limiter')); | ||
57 | +} | ||
58 | + | ||
54 | // 指定libray目录 | 59 | // 指定libray目录 |
55 | global.utils = path.resolve('./utils'); | 60 | global.utils = path.resolve('./utils'); |
56 | 61 |
apps/3party/controllers/check.js
0 → 100644
1 | +'use strict'; | ||
2 | +const _ = require('lodash'); | ||
3 | +const cache = global.yoho.cache.master; | ||
4 | + | ||
5 | +exports.index = (req, res) => { | ||
6 | + res.render('check', { | ||
7 | + width750: true, | ||
8 | + localCss: true | ||
9 | + }); | ||
10 | +}; | ||
11 | + | ||
12 | +exports.submit = (req, res) => { | ||
13 | + let captchaCode = _.get(req.session, 'captcha'); | ||
14 | + let remoteIp = req.get('X-Forwarded-For') || req.ip; | ||
15 | + | ||
16 | + if (remoteIp.indexOf(',') > 0) { | ||
17 | + let arr = remoteIp.split(','); | ||
18 | + | ||
19 | + remoteIp = arr[0]; | ||
20 | + } | ||
21 | + | ||
22 | + if (req.body.captcha === captchaCode) { | ||
23 | + let key = `pc:limiter:${remoteIp}`; | ||
24 | + cache.delAsync(key).then(() => { | ||
25 | + return res.json({ | ||
26 | + code: 200 | ||
27 | + }); | ||
28 | + }).catch(() => { | ||
29 | + return res.json({ | ||
30 | + code: 400 | ||
31 | + }); | ||
32 | + }); | ||
33 | + } else { | ||
34 | + return res.json({ | ||
35 | + code: 400 | ||
36 | + }); | ||
37 | + } | ||
38 | + | ||
39 | +}; |
@@ -9,9 +9,12 @@ | @@ -9,9 +9,12 @@ | ||
9 | const router = require('express').Router(); // eslint-disable-line | 9 | const router = require('express').Router(); // eslint-disable-line |
10 | const cRoot = './controllers'; | 10 | const cRoot = './controllers'; |
11 | const ads = require(`${cRoot}/ads`); | 11 | const ads = require(`${cRoot}/ads`); |
12 | +const check = require(`${cRoot}/check`); | ||
12 | 13 | ||
13 | // routers | 14 | // routers |
14 | 15 | ||
15 | router.get('/ads', ads.index); | 16 | router.get('/ads', ads.index); |
17 | +router.get('/check', check.index); | ||
18 | +router.post('/check/submit', check.submit); | ||
16 | 19 | ||
17 | module.exports = router; | 20 | module.exports = router; |
apps/3party/views/action/check.hbs
0 → 100644
apps/3party/views/partial/.gitkeep
0 → 100644
@@ -181,6 +181,7 @@ exports.orderSub = (req, res, next) => { | @@ -181,6 +181,7 @@ exports.orderSub = (req, res, next) => { | ||
181 | let yohoCoin = req.body.yohoCoin || 0; | 181 | let yohoCoin = req.body.yohoCoin || 0; |
182 | let skuList = req.body.skuList || ''; | 182 | let skuList = req.body.skuList || ''; |
183 | let orderInfo; | 183 | let orderInfo; |
184 | + let isWechat = req.yoho.isWechat; | ||
184 | 185 | ||
185 | try { | 186 | try { |
186 | orderInfo = JSON.parse(req.cookies['order-info']); | 187 | orderInfo = JSON.parse(req.cookies['order-info']); |
@@ -260,11 +261,11 @@ exports.orderSub = (req, res, next) => { | @@ -260,11 +261,11 @@ exports.orderSub = (req, res, next) => { | ||
260 | 261 | ||
261 | result = yield cartModel.orderSub(uid, addressId, 'bundle', deliveryTimeId, | 262 | result = yield cartModel.orderSub(uid, addressId, 'bundle', deliveryTimeId, |
262 | deliveryId, invoices, paymentTypeId, paymentType, msg, couponCode, | 263 | deliveryId, invoices, paymentTypeId, paymentType, msg, couponCode, |
263 | - yohoCoin, null, unionKey, userAgent, times, activityInfo, ip); | 264 | + yohoCoin, null, unionKey, userAgent, times, activityInfo, ip, isWechat); |
264 | } else { | 265 | } else { |
265 | result = yield cartModel.orderSub(uid, addressId, cartType, deliveryTimeId, | 266 | result = yield cartModel.orderSub(uid, addressId, cartType, deliveryTimeId, |
266 | deliveryId, invoices, paymentTypeId, paymentType, msg, couponCode, | 267 | deliveryId, invoices, paymentTypeId, paymentType, msg, couponCode, |
267 | - yohoCoin, skuList, unionKey, userAgent, null, null, ip); | 268 | + yohoCoin, skuList, unionKey, userAgent, null, null, ip, isWechat); |
268 | } | 269 | } |
269 | 270 | ||
270 | // 提交成功清除Cookie | 271 | // 提交成功清除Cookie |
@@ -178,12 +178,13 @@ exports.ticketsOrderCompute = (uid, productSku, buyNumber, yohoCoin) => { | @@ -178,12 +178,13 @@ exports.ticketsOrderCompute = (uid, productSku, buyNumber, yohoCoin) => { | ||
178 | * @param string|null $userAgent 联盟过来用户下单时需要的User-Agent信息 | 178 | * @param string|null $userAgent 联盟过来用户下单时需要的User-Agent信息 |
179 | * @param int $times | 179 | * @param int $times |
180 | * @param null $activityInfo 套餐数据 | 180 | * @param null $activityInfo 套餐数据 |
181 | + * @param isWechat 是否是微信商城 | ||
181 | * @return array 接口返回的数据 | 182 | * @return array 接口返回的数据 |
182 | */ | 183 | */ |
183 | exports.orderSub = (uid, addressId, cartType, deliveryTime, | 184 | exports.orderSub = (uid, addressId, cartType, deliveryTime, |
184 | deliveryWay, invoices, paymentId, paymentType, remark, | 185 | deliveryWay, invoices, paymentId, paymentType, remark, |
185 | couponCode, yohoCoin, skuList, qhyUnio, | 186 | couponCode, yohoCoin, skuList, qhyUnio, |
186 | - userAgent, times, activityInfo, ip) => { | 187 | + userAgent, times, activityInfo, ip, isWechat) => { |
187 | if (!qhyUnio) { | 188 | if (!qhyUnio) { |
188 | qhyUnio = ''; | 189 | qhyUnio = ''; |
189 | } | 190 | } |
@@ -215,7 +216,7 @@ exports.orderSub = (uid, addressId, cartType, deliveryTime, | @@ -215,7 +216,7 @@ exports.orderSub = (uid, addressId, cartType, deliveryTime, | ||
215 | return shoppingAPI.orderSub(uid, addressId, cartType, deliveryTime, | 216 | return shoppingAPI.orderSub(uid, addressId, cartType, deliveryTime, |
216 | deliveryWay, invoices, paymentId, paymentType, | 217 | deliveryWay, invoices, paymentId, paymentType, |
217 | remark, couponCode, yohoCoin, skuList, qhyUnio, | 218 | remark, couponCode, yohoCoin, skuList, qhyUnio, |
218 | - userAgent, times, activityInfo, ip).then(orderSubRes => { | 219 | + userAgent, times, activityInfo, ip, isWechat).then(orderSubRes => { |
219 | let finalResult = {}; | 220 | let finalResult = {}; |
220 | 221 | ||
221 | if (orderSubRes && orderSubRes.data && orderSubRes.data.is_hint === 'Y') { | 222 | if (orderSubRes && orderSubRes.data && orderSubRes.data.is_hint === 'Y') { |
@@ -111,7 +111,9 @@ const local = { | @@ -111,7 +111,9 @@ const local = { | ||
111 | res.render('login', { | 111 | res.render('login', { |
112 | width750: true, | 112 | width750: true, |
113 | loginIndex: true, // 模板中使用JS的标识 | 113 | loginIndex: true, // 模板中使用JS的标识 |
114 | - captchaShow: _.get(req.session, 'login.errorCount') <= 0, | 114 | + |
115 | + // captchaShow: _.get(req.session, 'login.errorCount') <= 0, | ||
116 | + captchaShow: true, // 170306 因为暴力破解密码问题,要求每次都展示验证码 | ||
115 | 117 | ||
116 | // 返回的URL链接 | 118 | // 返回的URL链接 |
117 | backUrl: 'javascript:history.go(-1)', // eslint-disable-line | 119 | backUrl: 'javascript:history.go(-1)', // eslint-disable-line |
@@ -162,7 +164,9 @@ const local = { | @@ -162,7 +164,9 @@ const local = { | ||
162 | // 返回的URL链接 | 164 | // 返回的URL链接 |
163 | backUrl: 'javascript:history.go(-1)', // eslint-disable-line | 165 | backUrl: 'javascript:history.go(-1)', // eslint-disable-line |
164 | loginInternational: true, // 模板中使用JS的标识 | 166 | loginInternational: true, // 模板中使用JS的标识 |
165 | - captchaShow: _.get(req.session, 'login.errorCount') <= 0, | 167 | + |
168 | + // captchaShow: _.get(req.session, 'login.errorCount') <= 0, | ||
169 | + captchaShow: true, // 170306 因为暴力破解密码问题,要求每次都展示验证码 | ||
166 | isPassportPage: true, // 模板中模块标识 | 170 | isPassportPage: true, // 模板中模块标识 |
167 | headerText: '登录', | 171 | headerText: '登录', |
168 | areaCode: '+86', // 默认区号 | 172 | areaCode: '+86', // 默认区号 |
@@ -173,6 +177,10 @@ const local = { | @@ -173,6 +177,10 @@ const local = { | ||
173 | }); | 177 | }); |
174 | }, | 178 | }, |
175 | login: (req, res, next) => { | 179 | login: (req, res, next) => { |
180 | + | ||
181 | + // 170306 因为暴力破解密码问题,要求每次都校验验证码 | ||
182 | + _.set(req.session, 'login.errorCount', 0); | ||
183 | + | ||
176 | let count = _.get(req.session, 'login.errorCount'); | 184 | let count = _.get(req.session, 'login.errorCount'); |
177 | 185 | ||
178 | if (count == null) { // eslint-disable-line | 186 | if (count == null) { // eslint-disable-line |
@@ -153,11 +153,12 @@ exports.checkTickets = (uid, productSku, buyNumber, useYohoCoin, yohoCoinMode) = | @@ -153,11 +153,12 @@ exports.checkTickets = (uid, productSku, buyNumber, useYohoCoin, yohoCoinMode) = | ||
153 | * @param string|null $userAgent 联盟过来用户下单时需要的User-Agent信息 | 153 | * @param string|null $userAgent 联盟过来用户下单时需要的User-Agent信息 |
154 | * @param $times | 154 | * @param $times |
155 | * @param null $activityInfo 套餐信息 | 155 | * @param null $activityInfo 套餐信息 |
156 | + * @param isWechat 是否是微信商城 | ||
156 | * @return array 接口返回的数据 | 157 | * @return array 接口返回的数据 |
157 | */ | 158 | */ |
158 | exports.orderSub = (uid, addressId, cartType, deliveryTime, | 159 | exports.orderSub = (uid, addressId, cartType, deliveryTime, |
159 | deliveryWay, invoices, paymentId, paymentType, remark, couponCode, | 160 | deliveryWay, invoices, paymentId, paymentType, remark, couponCode, |
160 | - yohoCoin, skuList, qhyUnion, userAgent, times, activityInfo, ip) => { | 161 | + yohoCoin, skuList, qhyUnion, userAgent, times, activityInfo, ip, isWechat) => { |
161 | if (!activityInfo) { | 162 | if (!activityInfo) { |
162 | activityInfo = null; | 163 | activityInfo = null; |
163 | } | 164 | } |
@@ -226,6 +227,11 @@ exports.orderSub = (uid, addressId, cartType, deliveryTime, | @@ -226,6 +227,11 @@ exports.orderSub = (uid, addressId, cartType, deliveryTime, | ||
226 | params.qhy_union = qhyUnion; | 227 | params.qhy_union = qhyUnion; |
227 | } | 228 | } |
228 | 229 | ||
230 | + // 是否是微信商城 | ||
231 | + if (isWechat) { | ||
232 | + params.client_type = 'wechat'; | ||
233 | + } | ||
234 | + | ||
229 | return api.post('', params, { | 235 | return api.post('', params, { |
230 | headers: { | 236 | headers: { |
231 | 'X-Forwarded-For': ip || '', | 237 | 'X-Forwarded-For': ip || '', |
@@ -72,7 +72,6 @@ module.exports = { | @@ -72,7 +72,6 @@ module.exports = { | ||
72 | udp: { // send by udp | 72 | udp: { // send by udp |
73 | measurement: 'yohobuy_wap_node_log', | 73 | measurement: 'yohobuy_wap_node_log', |
74 | level: 'error', // logger level | 74 | level: 'error', // logger level |
75 | - host: 'influxdblog.web.yohoops.org', // influxdb host | ||
76 | port: '4444' // influxdb port | 75 | port: '4444' // influxdb port |
77 | }, | 76 | }, |
78 | console: { | 77 | console: { |
@@ -107,7 +106,8 @@ module.exports = { | @@ -107,7 +106,8 @@ module.exports = { | ||
107 | key: '7e6f3307b64cc87c79c472814b88f7fb', | 106 | key: '7e6f3307b64cc87c79c472814b88f7fb', |
108 | appSecret: 'ce21ae4a3f93852279175a167e54509b', | 107 | appSecret: 'ce21ae4a3f93852279175a167e54509b', |
109 | notifyUrl: domains.service + 'payment/weixin_notify', | 108 | notifyUrl: domains.service + 'payment/weixin_notify', |
110 | - } | 109 | + }, |
110 | + maxQps: 1200 | ||
111 | }; | 111 | }; |
112 | 112 | ||
113 | if (isProduction) { | 113 | if (isProduction) { |
doraemon/middleware/limiter.js
0 → 100644
doraemon/middleware/limiter/index.js
0 → 100644
1 | +'use strict'; | ||
2 | + | ||
3 | +const _ = require('lodash'); | ||
4 | +const logger = global.yoho.logger; | ||
5 | +const ip = require('./rules/ip-list'); | ||
6 | +const userAgent = require('./rules/useragent'); | ||
7 | +const qpsLimiter = require('./rules/qps-limit'); | ||
8 | +const fakerLimiter = require('./rules/faker-limit'); | ||
9 | +const captchaPolicy = require('./policies/captcha'); | ||
10 | +const reporterPolicy = require('./policies/reporter'); | ||
11 | + | ||
12 | +const IP_WHITE_LIST = [ | ||
13 | + // '106.38.38.146', | ||
14 | + // '218.94.75.58' | ||
15 | +]; | ||
16 | + | ||
17 | +const limiter = (rule, policy, context) => { | ||
18 | + return rule(context, policy); | ||
19 | +}; | ||
20 | + | ||
21 | +module.exports = (req, res, next) => { | ||
22 | + let remoteIp = req.get('X-Forwarded-For') || req.connection.remoteAddress; | ||
23 | + logger.debug('request remote ip: ', remoteIp); | ||
24 | + | ||
25 | + if (remoteIp.indexOf(',') > 0) { | ||
26 | + let arr = remoteIp.split(','); | ||
27 | + | ||
28 | + remoteIp = arr[0]; | ||
29 | + } | ||
30 | + | ||
31 | + const excluded = _.includes(IP_WHITE_LIST, remoteIp); | ||
32 | + const enabled = !_.get(req.app.locals, 'wap.sys.noLimiter'); | ||
33 | + | ||
34 | + // 判断获取remoteIp成功,并且开关未关闭 | ||
35 | + if (enabled && remoteIp && !excluded) { | ||
36 | + const context = { | ||
37 | + req: req, | ||
38 | + res: res, | ||
39 | + next: next, | ||
40 | + remoteIp: remoteIp | ||
41 | + }; | ||
42 | + | ||
43 | + Promise.all([ | ||
44 | + limiter(userAgent, captchaPolicy, context), | ||
45 | + limiter(ip, captchaPolicy, context), | ||
46 | + limiter(qpsLimiter, captchaPolicy, context), | ||
47 | + //limiter(fakerLimiter, reporterPolicy, context) | ||
48 | + ]).then((results) => { | ||
49 | + let allPass = true, exclusion = false, policy = null; | ||
50 | + | ||
51 | + logger.debug('limiter result: ' + JSON.stringify(results)); | ||
52 | + | ||
53 | + _.forEach(results, (result) => { | ||
54 | + if (typeof result === 'object' && !exclusion) { | ||
55 | + exclusion = result.exclusion; | ||
56 | + } | ||
57 | + | ||
58 | + if (!excluded && typeof result === 'function') { | ||
59 | + allPass = false; | ||
60 | + } | ||
61 | + | ||
62 | + if (typeof result === 'function') { | ||
63 | + policy = result; | ||
64 | + } | ||
65 | + }); | ||
66 | + | ||
67 | + if (exclusion) { | ||
68 | + return next(); | ||
69 | + } else if (!allPass && policy) { | ||
70 | + policy(req, res, next); | ||
71 | + } else { | ||
72 | + return next(); | ||
73 | + } | ||
74 | + | ||
75 | + }).catch((err) => { | ||
76 | + logger.error(err); | ||
77 | + return next(); | ||
78 | + }); | ||
79 | + } else { | ||
80 | + return next(); | ||
81 | + } | ||
82 | +}; |
1 | +'use strict'; | ||
2 | + | ||
3 | +const helpers = global.yoho.helpers; | ||
4 | +const _ = require('lodash'); | ||
5 | + | ||
6 | +const WHITE_LIST = [ | ||
7 | + '/3party/check', | ||
8 | + '/passport/imagesNode', | ||
9 | + '/passport/cert/headerTip', | ||
10 | + '/passport/captcha/get', | ||
11 | + '/3party/check/submit' | ||
12 | +]; | ||
13 | + | ||
14 | +module.exports = (req, res, next) => { | ||
15 | + let refer = req.method === 'GET' ? req.get('Referer') : ''; | ||
16 | + let limitAPI = helpers.urlFormat('/3party/check', {refer: refer}); | ||
17 | + let limitPage = helpers.urlFormat('/3party/check', {refer: req.protocol + '://' + req.get('host') + req.originalUrl}); | ||
18 | + | ||
19 | + if (_.indexOf(WHITE_LIST, req.path) >= 0) { | ||
20 | + return next(); | ||
21 | + } | ||
22 | + | ||
23 | + if (req.xhr) { | ||
24 | + return res.json({ | ||
25 | + code: 400, | ||
26 | + data: {refer: limitAPI} | ||
27 | + }); | ||
28 | + } | ||
29 | + | ||
30 | + return res.redirect(limitPage); | ||
31 | +}; |
1 | +'use strict'; | ||
2 | + | ||
3 | +const logger = global.yoho.logger; | ||
4 | +const cache = global.yoho.cache.master; | ||
5 | +const ONE_DAY = 60 * 60 * 24; | ||
6 | + | ||
7 | +module.exports = (limiter, policy) => { | ||
8 | + const req = limiter.req, | ||
9 | + res = limiter.res, | ||
10 | + next = limiter.next; | ||
11 | + | ||
12 | + const key = `pc:limiter:faker:${limiter.remoteIp}`; | ||
13 | + | ||
14 | + if (req.header('X-Requested-With') === 'XMLHttpRequest') { | ||
15 | + cache.decrAsync(key, 1); | ||
16 | + } | ||
17 | + | ||
18 | + res.on('render', function() { | ||
19 | + cache.incrAsync(key, 1); | ||
20 | + }); | ||
21 | + | ||
22 | + return cache.getAsync(key).then((result) => { | ||
23 | + if (result) { | ||
24 | + if (result > 100) { | ||
25 | + return Promise.resolve(policy);//policy(req, res, next); | ||
26 | + } else { | ||
27 | + return Promise.resolve(true); | ||
28 | + } | ||
29 | + } else { | ||
30 | + cache.setAsync(key, 1, ONE_DAY); // 设置key,1m失效 | ||
31 | + return Promise.resolve(true); | ||
32 | + } | ||
33 | + }); | ||
34 | +}; |
doraemon/middleware/limiter/rules/ip-list.js
0 → 100644
1 | +'use strict'; | ||
2 | + | ||
3 | +const cache = global.yoho.cache.master; | ||
4 | +const _ = require('lodash'); | ||
5 | + | ||
6 | +module.exports = (limiter) => { | ||
7 | + const key = `pc:limiter:${limiter.remoteIp}`; | ||
8 | + | ||
9 | + return cache.getAsync(key).then((result) => { | ||
10 | + if (result && _.isNumber(result)) { | ||
11 | + return Promise.resolve({ | ||
12 | + exclusion: result === -1 | ||
13 | + }); | ||
14 | + } else { | ||
15 | + return Promise.resolve(true); | ||
16 | + } | ||
17 | + }); | ||
18 | +}; |
1 | +'use strict'; | ||
2 | + | ||
3 | +const logger = global.yoho.logger; | ||
4 | +const cache = global.yoho.cache.master; | ||
5 | +const config = global.yoho.config; | ||
6 | +const ONE_DAY = 60 * 60 * 24; | ||
7 | +const MAX_QPS = config.maxQps; | ||
8 | +const _ = require('lodash'); | ||
9 | + | ||
10 | +const PAGES = { | ||
11 | + '/product/\\/pro_([\\d]+)_([\\d]+)\\/(.*)/': 5, | ||
12 | + '/product/list/index': 5 | ||
13 | +}; | ||
14 | + | ||
15 | +function urlJoin(a, b) { | ||
16 | + if (_.endsWith(a, '/') && _.startsWith(b, '/')) { | ||
17 | + return a + b.substring(1, b.length); | ||
18 | + } else if (!_.endsWith(a, '/') && !_.startsWith(b, '/')) { | ||
19 | + return a + '/' + b; | ||
20 | + } else { | ||
21 | + return a + b; | ||
22 | + } | ||
23 | +} | ||
24 | + | ||
25 | +module.exports = (limiter, policy) => { | ||
26 | + const req = limiter.req, | ||
27 | + res = limiter.res, | ||
28 | + next = limiter.next; | ||
29 | + | ||
30 | + const key = `pc:limiter:${limiter.remoteIp}`; | ||
31 | + | ||
32 | + res.on('render', function() { | ||
33 | + let route = req.route ? req.route.path : ''; | ||
34 | + let appPath = req.app.mountpath; | ||
35 | + | ||
36 | + if (_.isArray(route) && route.length > 0) { | ||
37 | + route = route[0]; | ||
38 | + } | ||
39 | + | ||
40 | + let pageKey = urlJoin(appPath, route.toString()); // route may be a regexp | ||
41 | + let pageIncr = PAGES[pageKey] || 0; | ||
42 | + | ||
43 | + if (/^\/p([\d]+)/.test(req.path)) { | ||
44 | + pageIncr = 5; | ||
45 | + } | ||
46 | + | ||
47 | + if (pageIncr > 0) { | ||
48 | + cache.incrAsync(key, pageIncr, (err) => {}); | ||
49 | + } | ||
50 | + }); | ||
51 | + | ||
52 | + return cache.getAsync(key).then((result) => { | ||
53 | + logger.debug('qps limiter: ' + key + '@' + result + ' max: ' + MAX_QPS); | ||
54 | + | ||
55 | + if (result && _.isNumber(result)) { | ||
56 | + | ||
57 | + if (result === -1) { | ||
58 | + return Promise.resolve(true); | ||
59 | + } | ||
60 | + | ||
61 | + if (result > MAX_QPS) { // 判断 qps | ||
62 | + cache.touch(key, ONE_DAY); | ||
63 | + logger.debug('req limit', key); | ||
64 | + | ||
65 | + return Promise.resolve(policy); | ||
66 | + } else { | ||
67 | + cache.incrAsync(key, 1); // qps + 1 | ||
68 | + return Promise.resolve(true); | ||
69 | + | ||
70 | + } | ||
71 | + } else { | ||
72 | + cache.setAsync(key, 1, 60); // 设置key,1m失效 | ||
73 | + return Promise.resolve(true); | ||
74 | + } | ||
75 | + }); | ||
76 | +}; |
1 | +'use strict'; | ||
2 | + | ||
3 | +const cache = global.yoho.cache.master; | ||
4 | +const _ = require('lodash'); | ||
5 | +const logger = global.yoho.logger; | ||
6 | + | ||
7 | + | ||
8 | +module.exports = (limiter, policy) => { | ||
9 | + const req = limiter.req, | ||
10 | + res = limiter.res, | ||
11 | + next = limiter.next; | ||
12 | + const blackKey = 'pc:limiter:ua:black', | ||
13 | + whiteKey = 'pc:limiter:ua:white'; | ||
14 | + | ||
15 | + const ua = limiter.req.header('User-Agent'); | ||
16 | + | ||
17 | + return Promise.all([ | ||
18 | + cache.getAsync(blackKey), | ||
19 | + cache.getAsync(whiteKey) | ||
20 | + ]).then((args) => { | ||
21 | + const blacklist = args[0] || [], whitelist = args[1] || []; | ||
22 | + | ||
23 | + if (blacklist.length === 0 && whitelist.length === 0) { | ||
24 | + return Promise.resolve(true); | ||
25 | + } | ||
26 | + | ||
27 | + const test = (list) => { | ||
28 | + let result = false; | ||
29 | + | ||
30 | + _.each(list, (item) => { | ||
31 | + let regexp; | ||
32 | + | ||
33 | + try { | ||
34 | + regexp = new RegExp(item); | ||
35 | + } catch (e) { | ||
36 | + logger.error(e); | ||
37 | + } | ||
38 | + | ||
39 | + if (regexp.test(ua)) { | ||
40 | + result = true; | ||
41 | + } | ||
42 | + }); | ||
43 | + | ||
44 | + return result; | ||
45 | + }; | ||
46 | + | ||
47 | + if (test(blacklist)) { | ||
48 | + return Promise.resolve(policy); | ||
49 | + } else if (test(whitelist)) { | ||
50 | + return Promise.resolve({ | ||
51 | + exclusion: true | ||
52 | + }); | ||
53 | + } else { | ||
54 | + return Promise.resolve(true); | ||
55 | + } | ||
56 | + }); | ||
57 | + | ||
58 | +}; |
public/js/3party/check.page.js
0 → 100644
1 | +require('3party/check.page.css'); | ||
2 | +require('../common'); | ||
3 | +// 图片验证码 | ||
4 | +let ImgCheck = require('plugin/img-check'); | ||
5 | + | ||
6 | +let imgCheck = new ImgCheck('#js-img-check', { | ||
7 | + useREM: { | ||
8 | + rootFontSize: 40, | ||
9 | + picWidth: 150 | ||
10 | + } | ||
11 | +}); | ||
12 | + | ||
13 | +imgCheck.init(); | ||
14 | + | ||
15 | +$(function() { | ||
16 | + $('.submit').on('click', function() { | ||
17 | + $.ajax({ | ||
18 | + method: 'POST', | ||
19 | + url: '/3party/check/submit', | ||
20 | + data: { | ||
21 | + captcha: $.trim(imgCheck.getResults()) | ||
22 | + }, | ||
23 | + success: function(ret) { | ||
24 | + if (ret.code === 200) { | ||
25 | + window.location.href = decodeURIComponent(window.queryString.refer) || '//m.yohobuy.com'; | ||
26 | + } else { | ||
27 | + imgCheck.refresh(); | ||
28 | + } | ||
29 | + } | ||
30 | + }); | ||
31 | + }); | ||
32 | +}); |
@@ -18,9 +18,9 @@ require('activity/promotion/promotion.page.css'); | @@ -18,9 +18,9 @@ require('activity/promotion/promotion.page.css'); | ||
18 | 18 | ||
19 | var share = require('../common/share'); | 19 | var share = require('../common/share'); |
20 | share({ | 20 | share({ |
21 | - title: 'YOHO!BUY有货邀请同学认证赠好礼!立享【学生专属】4大特权!', | 21 | + title: '【有货】学生认证看过来!专享特价,任性分期,立即走起→', |
22 | link: location.href, | 22 | link: location.href, |
23 | - desc: '每邀请1名同学完成认证立赠300有货币!上不封顶!', | 23 | + desc: '邀请同学认证更有惊喜好礼相送~', |
24 | imgUrl: 'http://img11.static.yhbimg.com/taobaocms/2017/01/17/16/0108d724a0ef1f001d3ee6010aa79d960e.png' | 24 | imgUrl: 'http://img11.static.yhbimg.com/taobaocms/2017/01/17/16/0108d724a0ef1f001d3ee6010aa79d960e.png' |
25 | }); | 25 | }); |
26 | 26 | ||
@@ -303,9 +303,9 @@ $( | @@ -303,9 +303,9 @@ $( | ||
303 | var shareUrl = location.href.replace('userUid=', 'oldUid='); | 303 | var shareUrl = location.href.replace('userUid=', 'oldUid='); |
304 | 304 | ||
305 | share({ | 305 | share({ |
306 | - title: 'YOHO!BUY有货邀请同学认证赠好礼!立享【学生专属】4大特权!', | 306 | + title: '【有货】学生认证看过来!专享特价,任性分期,立即走起→', |
307 | link: shareUrl, | 307 | link: shareUrl, |
308 | - desc: '每邀请1名同学完成认证立赠300有货币!上不封顶!', | 308 | + desc: '邀请同学认证更有惊喜好礼相送~', |
309 | imgUrl: 'http://img11.static.yhbimg.com/taobaocms/2017/01/17/16/0108d724a0ef1f001d3ee6010aa79d960e.png' | 309 | imgUrl: 'http://img11.static.yhbimg.com/taobaocms/2017/01/17/16/0108d724a0ef1f001d3ee6010aa79d960e.png' |
310 | }); | 310 | }); |
311 | } | 311 | } |
@@ -46,7 +46,7 @@ function switchLoginBtnStatus() { | @@ -46,7 +46,7 @@ function switchLoginBtnStatus() { | ||
46 | } | 46 | } |
47 | 47 | ||
48 | function resetForm() { | 48 | function resetForm() { |
49 | - $pwd.val('').focus(); | 49 | + // $pwd.val('').focus(); |
50 | $loginBtn.text('登录').addClass('disable'); | 50 | $loginBtn.text('登录').addClass('disable'); |
51 | } | 51 | } |
52 | 52 | ||
@@ -123,7 +123,7 @@ $loginBtn.on('touchstart', function() { | @@ -123,7 +123,7 @@ $loginBtn.on('touchstart', function() { | ||
123 | type: 'POST', | 123 | type: 'POST', |
124 | url: '/passport/login/auth', | 124 | url: '/passport/login/auth', |
125 | data, | 125 | data, |
126 | - success: function(data) { | 126 | + success: function(data) { //eslint-disable-line |
127 | var res, | 127 | var res, |
128 | LOGI_TYPE; | 128 | LOGI_TYPE; |
129 | 129 |
@@ -101,8 +101,12 @@ function setPassword() { | @@ -101,8 +101,12 @@ function setPassword() { | ||
101 | showErrTip(data.message); | 101 | showErrTip(data.message); |
102 | } | 102 | } |
103 | }, | 103 | }, |
104 | - error: function() { | 104 | + error: function(data) { |
105 | $btnSure.removeClass('disable'); | 105 | $btnSure.removeClass('disable'); |
106 | + | ||
107 | + if (data && data.responseJSON && data.responseJSON.message) { | ||
108 | + showErrTip(data.message); | ||
109 | + } | ||
106 | } | 110 | } |
107 | }); | 111 | }); |
108 | } | 112 | } |
public/scss/3party/check.page.css
0 → 100644
1 | +@import "layout/img-check"; | ||
2 | + | ||
3 | +.check-page { | ||
4 | + margin: 20px auto; | ||
5 | + width: 700px; | ||
6 | + | ||
7 | + .submit { | ||
8 | + width: 100%; | ||
9 | + height: 100px; | ||
10 | + line-height: 100px; | ||
11 | + text-align: center; | ||
12 | + font-size: 32px; | ||
13 | + color: #fff; | ||
14 | + background: #5cb85c; | ||
15 | + border-radius: 10px; | ||
16 | + } | ||
17 | +} |
-
Please register or login to post a comment