google recaptcha v2 and v3

网站之前一直用的是google recaptcha v2 ,同一页面内如果有多个表单需要保护也很麻烦,官方也没什么文档。自己折腾了一下大致如下:

单页面多表单利用callback引入js:

<script src="https://www.google.com/recaptcha/api.js?onload=CaptchaCallback&render=explicit" async defer></script>
    <script type="text/javascript">
        var CaptchaCallback = function() {
            //表单一
            grecaptcha.render('g-recaptcha-news', {'sitekey' : '<?php echo Mage::helper('recaptcha')->getKey(); ?>'});
            //表单二
            grecaptcha.render('g-recaptcha-pop', {'sitekey' : '<?php echo Mage::helper('recaptcha')->getKey(); ?>'});
            //表单三
            grecaptcha.render('g-recaptcha-contact', {'sitekey' : '<?php echo Mage::helper('recaptcha')->getKey(); ?>'});
            
        };
</script>

还需要确保以上3个form里面分别有id为g-recaptcha-news、g-recaptcha-pop、g-recaptcha-contact的div与代码对应,如果js找不到这个id是会报错的;

后端php在表单控制器或者在表单控制器之前提交验证并返回,若失败则阻断表单提交即可;

public function Validate_captcha($response)
    {
        $verifyResponse = file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret=' . $this->getSecretkey() . '&response=' . $response);
        $responseData = json_decode($verifyResponse);
        if ($responseData->success):
            return true;
        else:
            return false;
        endif;
    }

v2总有个框有碍观瞻一直觉得很不爽,所以手欠换成了V3 invisible recaptcha 就是无感验证;然后发现这个就比较坑爹了;v3的思路跟v2差不多但有个很明显的缺陷就是超时了没办法自动刷新,因为V2验证超时了你还可以通过验证界面再次点击刷新token但是v3是没有界面的无处点击!

具体安装如下:

安装js在回调里面执行初始化方法,在需要验证的表单里面放入一个input用于接收token跟上面v2的div类似

var recaptchaScript = document.createElement('script');
            recaptchaScript.src = 'https://www.google.com/recaptcha/api.js?onload=mtInvisibleCaptchaOnloadCallback&render=<?php echo $captcha->getSiteKey(); ?>';
            recaptchaScript.attributes = 'async defer';
            document.body.appendChild(recaptchaScript);

window.mtInvisibleCaptchaOnloadCallback = function () {
            for (var i = 0; i < window.formToProtectOnPage.length; i++) {
                window.formToProtectOnPage[i].innerHTML +=
                    '<input class="invisible_token" type="hidden" name="invisible_token" value=""/>';
            }

            for (var i = 0; i < window.formToProtectOnPage.length; i++) {
                var form = window.formToProtectOnPage[i];
                if (form.tagName.toLowerCase() != 'form') {
                    continue;
                }
                currentFormId = form.id;
                currentFormId = currentFormId.replace(/\W+(?!$)/g, '');
                grecaptcha.ready(function() {
                    grecaptcha.execute('<?php echo $captcha->getSiteKey(); ?>', {action: currentFormId})
                        .then(function(token) {
                            $(".invisible_token").val(token);
                        });
                });
            }
        };

后端验证:

    public function verify($token)
    {
        $verification = array(
            'success' => false,
            'error' => ''
        );
        if ($token) {
            try {
                $secret = Mage::getStoreConfig(self::CONFIG_PATH_GENERAL_SECRET_KEY);
                $url = 'https://www.google.com/recaptcha/api/siteverify?secret=' .
                    $secret . '&response=' . $token . '&remoteip=' . $_SERVER["REMOTE_ADDR"];

                $ch = curl_init();
                curl_setopt($ch, CURLOPT_URL, $url);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                $response = curl_exec($ch);

                $result = json_decode($response, true);
                if ($result['success']) {
                    $verification['success'] = true;
                } elseif (array_key_exists('error-codes', $result)) {
                    $verification['error'] = $this->getErrorMessage($result['error-codes'][0]);
                }
            } catch (Exception $e) {
                $verification['error'] = $e->getMessage();
            }
        }

        return $verification;
    }

逻辑跟v2一样,唯一不同的我们需要额外处理超时的问题,谷歌的验证超时是大约2-3分钟,页面上的验证过了这段时间就过期了,但是用户如果不刷新页面是永远无法提交受保护的表单的,那么如何解此问题呢?

方法有2个:

1,在初始化的地方写一个定时器每2分钟执行一次获取验证码的方法,此方法优点就是可全局一次性搞定,缺点我就不说了很low的一种做法;

setInterval(function () {
                grecaptcha.execute('GOOGLE CLIENT KEY', { action: 'contact' }).then(function (token) {
                    if ($("#recaptcha_token").length) {
                        console.log("set new token to existing input >> token = " + token);
                        $("#recaptcha_token").val(token);
                    } else {
                        console.error("recaptcha_token does not exist on email_form");
                    }
                });
            }, 60000);

2、在提交表单的时候执行一次获取验证码的方法,此方法就是每个表单都要单独加代码比较麻烦点;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值