如何验证 Google Recaptcha V3 响应? [英] How to Verify Google Recaptcha V3 Response?

查看:134
本文介绍了如何验证 Google Recaptcha V3 响应?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在客户端和服务器端 (php) 中集成 Google reCAPTCHA 版本 3.以下代码用于显示recaptcha,但效果不佳.如何进行这种集成.

How to integrate Google reCAPTCHA Version 3 in Client Side and Server Side(php). following code use to display recaptcha but its not working good. How to do this integration.

<html>

<head>
  <script src='https://www.google.com/recaptcha/api.js?render=XXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'></script>
</head>

<body>
  <script>
    grecaptcha.ready(function() {
      grecaptcha.execute('XXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', {
        action: 'action_name'
      });
    });
  </script>

  <form action="verify.php" method="post">
    <input type="text" name="name" placeholder="Your name" required>
    <input type="email" name="email" placeholder="Your email address" required>
    <textarea name="message" placeholder="Type your message here...." required></textarea>

    <input type="submit" name="submit" value="SUBMIT">

  </form>

</body>

</html>

Verify.php

<?php

    if(isset($_POST['g-recaptcha-response']) && !empty($_POST['g-recaptcha-response'])) {
        //your site secret key
        $secret = 'XXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
        //get verify response data
        $verifyResponse = file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret='.$secret.'&response='.$_POST['g-recaptcha-response']);
        $responseData = json_decode($verifyResponse);
        if($responseData->success):

             print_r("Working Fine"); exit;
        else:
             print_r("No valid Key"); exit;
        endif;
    } else {
        print_r("Not Working Captcha"); exit;
    }

?>

推荐答案

Google reCAPTCHA v3 使用纯 JavaScript 和 PHP 验证的联系表单简单示例

tldr;跳到底部的代码.

A simple example of a contact form verified by Google reCAPTCHA v3 with pure JavaScript and PHP

tldr; skip to code at the bottom.

(如果谷歌正在倾听,我们喜欢你的工作,如果有一些更详细的例子链接到上述页面,那就太好了.)

(If Google are listening, we love your work and it would be wonderful to have some more elaborate examples linked to the above pages please.)

  1. 从 Google 获取密钥
  2. 在html的头部加载recaptcha/api.js
  3. 使用 JavaScript 劫持表单提交,然后从 Google 获取令牌
  4. 将带有令牌的表单提交到您的服务器
  5. 从您网站的后端向 Google 发出请求以验证表单提交
  6. 解释响应并根据需要继续

重要提示:'success' 响应参数仅表示验证码是否被成功评估,并不表示提交是否可能是垃圾邮件.

Important to note: the 'success' response parameter indicates only whether or not the captcha was evaluated successfully, it doesn't indicate whether the submission was likely to be spam or not.

'score' 参数是您需要了解的结果.分数越高(0 到 1 之间的数字),提交的内容就越有可能是真实的,接受的阈值(例如 0.5)取决于您.

The 'score' parameter is the result you need to know about. The higher the score (a number between 0 and 1) the more likely a submission is genuine, and it's upto you what threshold (e.g. 0.5) to accept.

将以下行添加到 HTML 的头部以加载 recaptcha api.js 代码:

Add the following line to the head of your HTML to load the recaptcha api.js code:

<script src="https://www.google.com/recaptcha/api.js?render=$reCAPTCHA_site_key"></script>

(其中 $reCAPTCHA_site_key 是您的公共站点密钥",我已将其保存在config.php"文件中.)

(where $reCAPTCHA_site_key is your public 'site key', which I've saved in a 'config.php' file.)

您需要向您的服务器提交一个令牌(从 Google 接收并且每个表单提交都是独一无二的).我认为通过 POST 连同表单数据的其余部分一起发送它是最简单的.为此,我在表单中包含一个隐藏字段,如下所示:

You need to submit a token (received from Google & unique to each form submission) to your server. I think it's simplest to send it via POST along with the rest of the form data. To that end I include a hidden field in the form as follows:

<form id="contactForm" method="post" action="contact">
    <!-- other form inputs -->
    <input type="hidden" id="gRecaptchaResponse" name="gRecaptchaResponse">
    <input type="submit" name="contact_submit" value="Send message">
</form>

(注意.联系人"是contact.php,但我已经用.htaccess重写"了网址)

(Nb. "contact" is contact.php, but I've 'rewritten' the url with .htaccess)

现在我们需要劫持默认的表单提交来生成令牌.我们可以在页面加载时生成令牌,但由于令牌仅在两分钟内有效(如果我正在阅读 https://developers.google.com/recaptcha/docs/verify 页面正确)我认为最好在需要将其发送到您网站的服务器时获取它.

Now we need to hijack the default form submission to generate the token. We could generate the token on page load but since the token is only valid for two minutes (if I'm reading the https://developers.google.com/recaptcha/docs/verify page correctly) I think it's better to fetch it at the point of needing to send it to your site's server.

为此,我在结束表单标签之后添加了以下内容:

To this end I added the following right after the closing form tag:

<script>
    contactForm.addEventListener('submit', event => {
        event.preventDefault()
        validate(contactForm)
    });
</script>

我已经将 validate(form) 函数放在结束正文标记之前:

I've put the validate(form) function just before the closing body tag:

function validate(form) {
    //perform optional error checking on form. If no errors then request a token and put it into the hidden field
    getRecaptchaToken(form)
}

//some other (optional) form validation functions

function getRecaptchaToken(form) {
    grecaptcha.ready(function() {
        grecaptcha.execute($reCAPTCHA_site_key, {action: 'contactForm'}).then(function(token) {
            gRecaptchaResponse.value = token //set the value of the hidden field
            form.submit() //submit the form
        });
    });
}

注意事项:

  • $reCAPTCHA_site_key 是您的公共站点密钥
  • action: 'contactForm' 标识此特定的提交Google reCAPTCHA 仪表板中的表单,并在后端确认它与预期一致是推荐的额外内容安全步骤
  • $reCAPTCHA_site_key is your public Site Key
  • action: 'contactForm' identifies the submission of this particular form in the Google reCAPTCHA dashboard, and confirming it is as expected in the backend is a recommended extra security step

在主 PHP 文件中,当收到表单提交时:

In the main PHP file, when the form submission is received:

//get the IP address of the origin of the submission
$ip = $_SERVER['REMOTE_ADDR'];

//construct the url to send your private Secret Key, token and (optionally) IP address of the form submitter to Google to get a spam rating for the submission (I've saved '$reCAPTCHA_secret_key' in config.php)
$url =  'https://www.google.com/recaptcha/api/siteverify?secret=' . urlencode($reCAPTCHA_secret_key) . '&response=' . urlencode($g_recaptcha_response) . '&remoteip=' . urlencode($ip);

//save the response, e.g. print_r($response) prints { "success": true, "challenge_ts": "2019-07-24T11:19:07Z", "hostname": "your-website-domain.co.uk", "score": 0.9, "action": "contactForm" }
$response = file_get_contents($url);

//decode the response, e.g. print_r($responseKeys) prints Array ( [success] => 1 [challenge_ts] => 2019-07-24T11:19:07Z [hostname] => your-website-domain.co.uk [score] => 0.9 [action] => contactForm )
$responseKeys = json_decode($response, true);

//check if the test was done OK, if the action name is correct and if the score is above your chosen threshold (again, I've saved '$g_recaptcha_allowable_score' in config.php)
if ($responseKeys["success"] && $responseKeys["action"] == 'contactForm') {
    if ($responseKeys["score"] >= $g_recaptcha_allowable_score) {
        //send email with contact form submission data to site owner/ submit to database/ etc
        //redirect to confirmation page or whatever you need to do
    } elseif ($responseKeys["score"] < $g_recaptcha_allowable_score) {
        //failed spam test. Offer the visitor the option to try again or use an alternative method of contact.
    }
} elseif($responseKeys["error-codes"]) { //optional
    //handle errors. See notes below for possible error codes
    //personally I'm probably going to handle errors in much the same way by sending myself a the error code for debugging and offering the visitor the option to try again or use an alternative method of contact
} else {
    //unkown screw up. Again, offer the visitor the option to try again or use an alternative method of contact.
}

注意事项:

  • 这是 Google 响应中的数据(作为 JSON 对象返回):


   {
     "success": true|false,      // whether this request was a valid reCAPTCHA token for your site
     "score": number             // the score for this request (0.0 - 1.0)
     "action": string            // the action name for this request (important to verify)
     "challenge_ts": timestamp,  // timestamp of the challenge load (ISO format yyyy-MM-dd'T'HH:mm:ssZZ)
     "hostname": string,         // the hostname of the site where the reCAPTCHA was solved
     "error-codes": [...]        // optional
   }

  • 这些是可能的错误代码:
    • missing-input-secret:缺少秘密参数.
    • invalid-input-secret:秘密参数无效或格式错误.
    • missing-input-response:缺少响应参数.
    • invalid-input-response:响应参数无效或格式错误.
    • bad-request:请求无效或格式错误.
    • timeout-or-duplicate:响应不再有效;要么太旧的或以前使用过.

    contact.php

    <?php  //contact.php
    
        require_once('config.php');
    
        //do server-side validation of other form fields
    
        if (/*form has been submitted and has passed server-side validation of the other form fields*/) {
            $ip = $_SERVER['REMOTE_ADDR'];
            $url =  'https://www.google.com/recaptcha/api/siteverify?secret=' . urlencode($reCAPTCHA_secret_key) . '&response=' . urlencode($g_recaptcha_response) . '&remoteip=' . urlencode($ip);
            $response = file_get_contents($url);
            $responseKeys = json_decode($response, true);
    
            if ($responseKeys["success"] && $responseKeys["action"] == 'contactForm') {
                if ($responseKeys["score"] >= $g_recaptcha_allowable_score) {
                    //send email with contact form submission data to site owner/ submit to database/ etc
                    //redirect to confirmation page or whatever you need to do
                } elseif ($responseKeys["score"] < $g_recaptcha_allowable_score) {
                    //failed spam test. Offer the visitor the option to try again or use an alternative method of contact.
                }
            } elseif($responseKeys["error-codes"]) { //optional
                //handle errors. See notes below for possible error codes
                //(I handle errors by sending myself an email with the error code for debugging and offering the visitor the option to try again or use an alternative method of contact)
            } else {
                //unkown screw up. Again, offer the visitor the option to try again or use an alternative method of contact.
            }
    
            exit;
    
        } else { //(re)display the page with the form
    
            echo <<<_END
    
                <!DOCTYPE html>
                <html lang="en">
                    <head>
                        <title>Contact | Your website</title>
                        <link rel="stylesheet" href="css/style.css">
                        <script src="https://www.google.com/recaptcha/api.js?render=$reCAPTCHA_site_key"></script>
                    </head>
                    <body>
    
                        <!-- header etc -->
    
                        <form id="contactForm" method="post" action="contact">
                            //other form inputs
                            <input type="hidden" id="gRecaptchaResponse" name="gRecaptchaResponse">
                            <input type="submit" name="contact_submit" value="Send message">
                        </form>
                        <script>
                            contactForm.addEventListener('submit', event => {
                                event.preventDefault()
                                validate(contactForm)
                            });
                        </script>
    
                        <!-- footer etc -->
    
                        <script>
                            function validate(form) {
                                //perform optional client-side error checking of the form. If no errors are found then request a token and put it into the hidden field. Finally submit the form.
                                getRecaptchaToken(form)
                            }
    
                            //some (optional) form field validation functions
    
                            function getRecaptchaToken(form) {
                                grecaptcha.ready(function() {
                                    grecaptcha.execute($reCAPTCHA_site_key, {action: 'contactForm'}).then(function(token) {
                                        gRecaptchaResponse.value = token
                                        form.submit()
                                    });
                                });
                            }
                        </script>
                    </body>
                </html>
    
    _END;
    

    config.php

    <?php //config.php
    
    //other site settings
    
    // Google reCAPTCHA v3 keys
    // For reducing spam contact form submissions
    
    // Site key (public)
    $reCAPTCHA_site_key = 'N0t-a-real-0N3_JHbnbUJ-BLAHBLAH_Blahblah';
    
    // Secret key
    $reCAPTCHA_secret_key = 'N0t-a-real-0N3_i77tyYGH7Ty6UfG-blah';
    
    // Min score returned from reCAPTCHA to allow form submission
    $g_recaptcha_allowable_score = 0.5; //Number between 0 and 1. You choose this. Setting a number closer to 0 will let through more spam, closer to 1 and you may start to block valid submissions.
    

    这篇关于如何验证 Google Recaptcha V3 响应?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆