validateCode.js 3.33 KB
/**
 * 验证码中间件
 * @author feng.chen<feng.chen@yoho.cn>
 * @date 2017/03/23
 */

'use strict';
const _ = require('lodash');
const config = global.yoho.config;
const co = Promise.coroutine;
const cache = global.yoho.cache;
const log = global.yoho.logger;
const geetest = require('./geetest');
const captcha = require('./captcha');
const imgCheck = require('../models/imgcheck');

/**
 * 加载验证码
 */
const load = (req, res, next) => {
    co(function* () {
        res.locals.useGeetest = _.get(req.app.locals.wap, 'geetest.validation', false); // 使用极验证
        if (res.locals.useGeetest) {
            req.yoho.captchaShow = false;
        } else {
            let isNeedImgCheckApiData = yield req.ctx(imgCheck).isNeedImgCheck();

            req.yoho.captchaShow = true;
            if (_.parseInt(_.get(isNeedImgCheckApiData, 'code')) === 200) {
                req.yoho.captchaShow = _.get(isNeedImgCheckApiData, 'data');
            }
        }

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

/**
 * 验证验证码
 */
const check = (req, res, next) => {
    let testCode = req.body.yohobuy;

    if (testCode === config.testCode) {
        return next();
    }

    // 默认取配置总开关来决定是否展示验证码
    req.yoho.captchaShow = _.get(req.app.locals.wap, 'close.loginValidation', false);

    co(function* () {
        // 如果是账号密码登录,那么需要检查是否登录失败过,登录失败过展示验证码
        if (req.path === '/passport/login/auth') {
            // 第一次登录要不要展示验证码:后台开关勾选,首次登录不需要展示
            let firstLoginShowCaptcha = !_.get(req.app.locals.wap, 'close.firstLoginShowCaptcha', false);

            log.info(`firstLoginShowCaptcha status is ${firstLoginShowCaptcha}`);

            if (firstLoginShowCaptcha) {
                req.yoho.captchaShow = true;
            } else {
                let hasErrorLog = yield cache.get(`loginErrorIp:${req.yoho.clientIp}`);

                log.info(`Check clientip ${req.yoho.clientIp} status is ` + hasErrorLog);

                if (hasErrorLog) {
                    req.yoho.captchaShow = true;
                } else {
                    req.yoho.captchaShow = false;
                }
            }
        }

        return req.yoho.captchaShow;
    })().catch(function() {
        // memcache 不可用,展示验证码
        req.yoho.captchaShow = true;
        return req.yoho.captchaShow;
    }).then(function() {
        // 不是账号密码登录,直接根据配置总开关决定是否需要展示验证码
        if (!req.yoho.captchaShow) {
            return next();
        }

        // 使用极验证
        let useGeetest = !_.get(req.app.locals.wap, 'geetest.validation', false);

        // 某次请求极验证调用注册失败,强制使用自有图形验证码
        if (req.session.useYohoCaptcha) {
            useGeetest = false;
        }

        return (useGeetest ? geetest : captcha).validate(req, res, next);
    });
};

module.exports = {
    load,
    check
};