php 如何验证 Google Recaptcha V3 响应

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/50405977/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 02:49:42  来源:igfitidea点击:

How to Verify Google Recaptcha V3 Response

phprecaptchainvisible-recaptcha

提问by Karthik

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.

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

<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

<?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;
    }

?>

回答by bsbak

<html>
    <head>
        <script src='https://www.google.com/recaptcha/api.js?render=6Le7-FkUAAAAADDSsTVBvpoUB5MkesNKgPVemFf-UD'></script>
    </head>
    <body> 
    <script>
    // when form is submit
    $('form').submit(function() { 
        // we stoped it
        event.preventDefault();
        // needs for recaptacha ready
        grecaptcha.ready(function() {
            // do request for recaptcha token
            // response is promise with passed token
            grecaptcha.execute('6Le7-FkUAAAAADDSsTVBvpoUB5MkesNKgPVemFf-UD', {action: 'create_comment'}).then(function(token) {
                // add token to form
                $('form').prepend('<input type="hidden" name="token" value="' + token + '">');
                $('form').prepend('<input type="hidden" name="action" value="create_comment">');
                // submit form now
                $('form').unbind('submit').submit();
            });;
        });
    });

    </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>

php

php

$token = $_POST['token'];
$secret = 'ur secret';
$action = $_POST['action'];
// now you need do a POST requst to google recaptcha server.
// url: https://www.google.com/recaptcha/api/siteverify.
// with data secret:$secret and response:$token 

At this point in the code, you will need to do a post request to ReCAPTCHA to verify the token, as documented here: https://www.google.com/recaptcha/api/siteverify. The response will be a json object with field "success" (true/false) and "action" for comparison (==) and score (number from 0.0 - 1.0)

此时在代码中,您需要向 ReCAPTCHA 发出发布请求以验证令牌,如此处所述:https: //www.google.com/recaptcha/api/siteverify。响应将是一个带有字段“成功”(真/假)和“动作”的 json 对象,用于比较(==)和分数(0.0 - 1.0 之间的数字)

https://developers.google.com/recaptcha/docs/v3#api-response.

https://developers.google.com/recaptcha/docs/v3#api-response

You can also specify action name for each request (create_post, update_post, create_comment ...)

您还可以为每个请求指定操作名称(create_post、update_post、create_comment ...)

回答by Bob

Try this.

尝试这个。

<script>
  grecaptcha.ready(function() {
   grecaptcha.execute('<site-secret>', {action: 'MyForm'})
   .then(function(token) {
    console.log(token)
    document.getElementById('g-recaptcha-response').value =    token;
   }); 
  }); 
 </script> 

<form action="verify.php" method="post">
  <input type="hidden" id="g-recaptcha-response" name="g-recaptcha-response">
  <input type="text" name="name" placeholder="Your name" required >
  <input type="email" name="email" placeholder="Your email address" required>
  <input type="submit" name="submit" value="SUBMIT" >
</form>

回答by wkille

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

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

tldr; skip to code at the bottom.

tldr; 跳到底部的代码。

Relevant reCAPTCHA docs etc:

相关 reCAPTCHA 文档等:

(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.)

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

Overview:

概述:

  1. Get keys from Google
  2. Load recaptcha/api.js in head of html
  3. HiHyman form submission with JavaScript and at that point get token from Google
  4. Submit form with token to your server
  5. Make request from your website's backend to Google to verify the form submission
  6. Interpret the response and proceed as necessary
  1. 从 Google 获取密钥
  2. 在 html 的头部加载 recaptcha/api.js
  3. 使用 JavaScript 劫持表单提交,然后从 Google 获取令牌
  4. 将带有令牌的表单提交到您的服务器
  5. 从您网站的后端向 Google 发出请求以验证表单提交
  6. 解释响应并根据需要继续

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.

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

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.

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

In detail:

详细:

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

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

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

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

$reCAPTCHA_site_key您的公共“站点密钥”在哪里,我已将其保存在“config.php”文件中。)

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:

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

<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>

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

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

Now we need to hiHyman 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/verifypage correctly) I think it's better to fetch it at the point of needing to send it to your site's server.

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

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

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

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

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

我已经把validate(form)函数放在结束 body 标签之前:

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
        });
    });
}

Notes:

笔记:

  • $reCAPTCHA_site_keyis 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
  • $reCAPTCHA_site_key是您的公共站点密钥
  • action: 'contactForm'在 Google reCAPTCHA 仪表板中识别此特定表单的提交,并在后端确认它如预期一样是推荐的额外安全步骤

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

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

//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.
}

Notes:

笔记:

  • This is is the data which will be in the response from Google (returned as a JSON object):
  • 这是 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
   }

  • These are the possible error codes:
    • missing-input-secret: The secret parameter is missing.
    • invalid-input-secret: The secret parameter is invalid or malformed.
    • missing-input-response: The response parameter is missing.
    • invalid-input-response: The response parameter is invalid or malformed.
    • bad-request: The request is invalid or malformed.
    • timeout-or-duplicate: The response is no longer valid; either is too old or has been used previously.
  • 这些是可能的错误代码:
    • 缺少输入秘密:缺少秘密参数。
    • invalid-input-secret:secret 参数无效或格式错误。
    • 缺少输入响应:缺少响应参数。
    • invalid-input-response:响应参数无效或格式错误。
    • bad-request:请求无效或格式错误。
    • timeout-or-duplicate:响应不再有效;要么太旧,要么以前使用过。

Putting it all together:

把它们放在一起:

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.

回答by Shaikh Shahid

Here is a sample working code with the demo.

这是带有演示的示例工作代码。

html side code

html端代码

<html>
  <head>
    <title>Google recapcha v3 demo - Codeforgeek</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
      <script src="https://www.google.com/recaptcha/api.js?render=put your site key here"></script>
  </head>
  <body>
    <h1>Google reCAPTHA Demo</h1>
    <form id="comment_form" action="form.php" method="post" >
      <input type="email" name="email" placeholder="Type your email" size="40"><br><br>
      <textarea name="comment" rows="8" cols="39"></textarea><br><br>
      <input type="submit" name="submit" value="Post comment"><br><br>
    </form>
      <script>
       // when form is submit
    $('#comment_form').submit(function() {
        // we stoped it
        event.preventDefault();
        var email = $('#email').val();
        var comment = $("#comment").val();
        // needs for recaptacha ready
        grecaptcha.ready(function() {
            // do request for recaptcha token
            // response is promise with passed token
            grecaptcha.execute('put your site key here', {action: 'create_comment'}).then(function(token) {
                // add token to form
                $('#comment_form').prepend('<input type="hidden" name="g-recaptcha-response" value="' + token + '">');
                    $.post("form.php",{email: email, comment: comment, token: token}, function(result) {
                            console.log(result);
                            if(result.success) {
                                    alert('Thanks for posting comment.')
                            } else {
                                    alert('You are spammer ! Get the @$%K out.')
                            }
                    });
            });;
        });
  });
  </script>
  </body>
</html>

PHP code.

PHP代码。

<?php

        $email;$comment;$captcha;
        if(isset($_POST['email'])){
          $email=$_POST['email'];
        }if(isset($_POST['comment'])){
          $comment=$_POST['comment'];
        }if(isset($_POST['token'])){
          $captcha=$_POST['token'];
          }
        if(!$captcha){
          echo '<h2>Please check the the captcha form.</h2>';
          exit;
        }
        $secretKey = "put your secret key here";
        $ip = $_SERVER['REMOTE_ADDR'];

        // post request to server

        $url =  'https://www.google.com/recaptcha/api/siteverify?secret=' . urlencode($secretKey) .  '&response=' . urlencode($captcha);
        $response = file_get_contents($url);
        $responseKeys = json_decode($response,true);
        header('Content-type: application/json');
        if($responseKeys["success"]) {
                echo json_encode(array('success' => 'true'));
        } else {
                echo json_encode(array('success' => 'false'));
        }
?>

Its working fine.

它的工作正常。

Demo: https://demo.codeforgeek.com/recaptcha-v3/

演示:https: //demo.codeforgeek.com/recaptcha-v3/

tutorial: https://codeforgeek.com/2019/02/google-recaptcha-v3-tutorial/

教程:https: //codeforgeek.com/2019/02/google-recaptcha-v3-tutorial/

回答by Giorgio C.

I'd like to give you a complete workflow to integrate recaptchav3 into an ASP.NET core MVC solution.

我想为您提供一个完整的工作流程,将 recaptchav3 集成到 ASP.NET 核心 MVC 解决方案中。

in your appsettings.json file:

在您的 appsettings.json 文件中:

  "RecaptchaSettings": {
    "Uri": "https://www.google.com/recaptcha/api/siteverify",
    "SecretKey": "your private key"
    "SiteKey": "your public key",
    "Version": "v3"
  }

in your view (@razor syntax):

在您看来(@razor 语法):

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

<script src="https://www.google.com/recaptcha/[email protected]("RecaptchaSettings")["SiteKey"]"></script>

    <script>
        grecaptcha.ready(function () {
            grecaptcha.execute('@Configuration.GetSection("RecaptchaSettings")["SiteKey"]',  { action: 'homepage' })
                .then(function (token) {

                    document.getElementById('g-recaptcha-response').value = token;
                });
        });
    </script>

and in your form put this:

并在您的表单中输入:

<form action="/">
…
<input type="hidden" id="g-recaptcha-response" name="g-recaptcha-response">
…

</form>

I create a simple method to manage it:

我创建了一个简单的方法来管理它:

public async Task<bool> ChallengePassed(string uri, string gRecaptchaResponse, string secret)
        {

            var concUri = uri + "?secret=" + secret + "&response=" + gRecaptchaResponse;

            var request = new HttpRequestMessage(HttpMethod.Get, concUri);
            var res = await _Client.SendAsync(request);

            if (!res.IsSuccessStatusCode)
            {
                return false;
            }

            var data = await res.Content.ReadAsStringAsync();

            dynamic JSONdata = JObject.Parse(data);
            if (JSONdata.success != "true")
            {
                return false;
            }

            return true;
        }

        #endregion

        #region PRIVATE

        #endregion

        #endregion

        #endregion
    }

and simply I called it into a Controller:

我只是将它调用到控制器中:

 //recaptcha validation

    bool isChallengeOk = await _CaptchaVerify.ChallengePassed(_Configuration.GetValue<string>("RecaptchaSettings:Uri"), Request.Form["g-recaptcha-response"], _Configuration.GetValue<string>("RecaptchaSettings:SecretKey"));

notice that I'm setting the input parameters from the "_Configuration" object, that represents an instance of configuration setting object in Startup.cs. You can pass manually input parameters to the method.

请注意,我正在从“_Configuration”对象设置输入参数,该对象表示 Startup.cs 中配置设置对象的一个​​实例。您可以将手动输入参数传递给该方法。

Enjoy it

好好享受