check.js 5.6 KB
'use strict';

const _ = require('lodash');
const headerModel = require('../../../doraemon/models/header');
const checkModel = require('..//models/check');
const decodeURIComponent = require('../../../utils/string-process').decodeURIComponent;
const logger = global.yoho.logger;
const Geetest = require('geetest');
const config = global.yoho.config;
const co = Promise.coroutine;
const cache = global.yoho.cache.master;
const captcha = new Geetest({
    geetest_id: 'bce95d796bc3058615fdf2ec2c0aef29',
    geetest_key: '124c41d3a22aa48f36ae3cd609c51db5'
});

exports.index = (req, res) => {
    req.yoho.captchaShow = false;

    if (req.session.apiRiskValidate) {
        res.locals.useRiskImg = true;
    } else {
        res.locals.useGeetest = true;
    }

    if (_.has(res, 'locals.loadJsBefore')) {
        res.locals.loadJsBefore.push({
            src: global.yoho.config.geetestJs
        });
    } else {
        res.locals.loadJsBefore = [
            {
                src: global.yoho.config.geetestJs
            }
        ];
    }

    res.render('check', {
        pageHeader: headerModel.setNav({
            navTitle: '友情提醒'
        }),
        width750: true,
        localCss: true
    });
};

const limitKey = 'limit2';

const submitValidate = {
    errRes: {
        code: 400,
        message: '验证码错误',
        captchaShow: true,
        changeCaptcha: true
    },
    clearLimitIp(req) {
        let remoteIp = req.yoho.clientIp;
        let operations = [];

        if (remoteIp.indexOf(',') > 0) {
            let arr = remoteIp.split(',');

            remoteIp = arr[0];
        }

        const isOpenApmrisk = _.get(req.app.locals, 'wap.open.apmrisk', false);

        // 新的计数
        if (isOpenApmrisk) {
            operations.push(cache.delAsync(`${config.app}:${limitKey}:${remoteIp}`));

            if (req.session.apiLimitValidate || req.session.apiRiskValidate) {
                operations.push(cache.setAsync(
                    `${config.app}:limiter:api:ishuman:${remoteIp}`,
                    1,
                    config.LIMITER_IP_TIME
                ));
            } else {
                operations.push(cache.setAsync(
                    `${config.app}:${limitKey}:ishuman:${remoteIp}`,
                    1,
                    config.LIMITER_IP_TIME
                ));

            }

            _.forEach(config.REQUEST_LIMIT, (val, key) => {
                operations.push(cache.delAsync(`${config.app}:${limitKey}:${key}:max:${remoteIp}`));
            });
        } else {
            operations.push(cache.delAsync(`${config.app}:limiter:${remoteIp}`));

            // 验证码之后一小时之内不再限制qps
            if (req.session.apiLimitValidate || req.session.apiRiskValidate) {
                operations.push(cache.setAsync(
                    `${config.app}:limiter:api:ishuman:${remoteIp}`,
                    1,
                    config.LIMITER_IP_TIME
                ));
            } else {
                operations.push(cache.setAsync(
                    `${config.app}:limiter:ishuman:${remoteIp}`,
                    1,
                    config.LIMITER_IP_TIME
                ));
            }

            _.forEach(config.REQUEST_LIMIT, (val, key) => {
                operations.push(cache.delAsync(`${config.app}:limiter:${key}:max:${remoteIp}`));
            });
        }

        delete req.session.apiLimitValidate;
        delete req.session.apiRiskValidate;

        if (req.body.pid) {
            let riskPid = decodeURIComponent(req.body.pid) + ':' + _.get(req.yoho, 'clientIp', '');

            operations.push(cache.delAsync(riskPid));
        }

        return Promise.all(operations);
    },
    geetest(req, res) {
        const self = this;

        co(function * () {
            let challenge = req.body.geetest_challenge,
                validate = req.body.geetest_validate,
                seccode = req.body.geetest_seccode;

            if (!challenge || !validate || !seccode) {
                return res.json(self.errRes);
            }

            let geetestRes = yield captcha.validate({
                challenge,
                validate,
                seccode
            });

            if (geetestRes) {
                logger.info('geetest success');

                yield self.clearLimitIp(req);

                // 图形验证码关闭时通过极验证后解锁接口风控
                if (req.session.apiRiskClear) {
                    delete req.session.apiRiskClear;
                    yield req.ctx(checkModel).verifyImgCheckRisk(req.cookies.udid, '1,2,3,4').catch(console.error);
                }

                return res.json({
                    code: 200
                });
            } else {
                logger.info('geetest faild');
                return res.json(self.errRes);
            }

        })();
    },
    imgCheckRisk(req, res) {
        const self = this;

        co(function*() {
            let result = yield req.ctx(checkModel).verifyImgCheckRisk(req.cookies.udid, req.body.captcha);

            if (result.code === 200) {
                yield self.clearLimitIp(req);

                return res.json(result);
            } else {
                logger.info('api risk img verify faild');
                return res.json(self.errRes);
            }
        })();
    }
};

exports.submit = (req, res) => {
    let validateType = 'geetest';

    if (req.session.apiRiskValidate && req.body.apiRiskValidate) {
        validateType = 'imgCheckRisk';
    }

    try {
        return submitValidate[validateType](req, res);
    } catch (err) {
        return res.json({
            code: 400
        });
    }
};