如何在服务器端验证Google reCAPTCHA v3?


73

我刚刚设置了带有复选框的新Google Recaptcha,它在前端工作正常,但是我不知道如何使用PHP在服务器端处理它。我尝试使用下面的旧代码,但是即使验证码无效,也会发送表格。

require_once('recaptchalib.php');
$privatekey = "my key";
$resp = recaptcha_check_answer ($privatekey,
        $_SERVER["REMOTE_ADDR"],
        $_POST["recaptcha_challenge_field"],
        $_POST["recaptcha_response_field"]);

if (!$resp->is_valid) {
 $errCapt='<p style="color:#D6012C ">The CAPTCHA Code wasnot entered correctly.</p>';}

检查它的被填充。if( strlen($_POST['recaptcha_challenge_field']) > 0) {}
ʰᵈˑ

感谢您的回复,但请您给我更多详细信息...
Moatez 2014年

我自己在联系表单上实现了此操作。我建议recaptchalib.php在此链接中使用新的Google提供的示例及其示例:github.com/google/ReCAPTCHA/tree/master/php
Ed Stenger

谢谢,但是很抱歉,我还不明白,我有两个文件contact.html和contact.php,第一个调用第二个,在第一个中,我将以下内容放在:</ head>之前:<script src = ' google.com/recaptcha/api.js ' ></script>在提交按钮<div class =“ g-recaptcha” data-sitekey =“ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx”> </ div>之前,但是在contact.php中我不知道我应该放??
Moatez 2014年

Answers:


107

这是解决方案

index.html

<html>
  <head>
    <title>Google recapcha demo - Codeforgeek</title>
    <script src='https://www.google.com/recaptcha/api.js'></script>
  </head>
  <body>
    <h1>Google reCAPTHA Demo</h1>
    <form id="comment_form" action="form.php" method="post">
      <input type="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>
      <div class="g-recaptcha" data-sitekey="=== Your site key ==="></div>
    </form>
  </body>
</html>

verify.php

<?php
    $email; $comment; $captcha;

    if(isset($_POST['email']))
        $email=$_POST['email'];
    if(isset($_POST['comment']))
        $comment=$_POST['comment'];
    if(isset($_POST['g-recaptcha-response']))
        $captcha=$_POST['g-recaptcha-response'];

    if(!$captcha){
        echo '<h2>Please check the the captcha form.</h2>';
        exit;
    }

    $response = json_decode(file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=YOUR SECRET KEY&response=".$captcha."&remoteip=".$_SERVER['REMOTE_ADDR']), true);
    if($response['success'] == false)
    {
        echo '<h2>You are spammer ! Get the @$%K out</h2>';
    }
    else
    {
        echo '<h2>Thanks for posting comment.</h2>';
    }
?>

http://codeforgeek.com/2014/12/google-recaptcha-tutorial/


15
reCAPTCHA表单字段值直接连接到验证URL中。攻击者可能会使用它在验证请求上注入任意形式的参数,从而有可能绕过CAPTCHA。要解决此问题,请按如下所示urlencode($captcha)
清除验证

2
此代码未编码攻击者可以用来破坏您的代码的参数。
Paul

6
数据应按照docs中的规定帐。此代码使用GET方法。我会对Levit的答案有所不同。
BTS

1
对我来说很好。除了(在index.html中)表格行:之外 action="form.php",应该为action="verify.php"

此代码适用于我的共享主机,而不适用于VPS服务器。是否有与服务器链接的要求?
Mohammed Kumel

115

私钥安全

虽然这里的答案肯定有效,但是它们使用的是GET请求,该请求公开了您的私钥(即使https已使用)。在Google Developers上,指定的方法是POST

有关更多详细信息:https : //stackoverflow.com/a/323286/1680919

通过POST验证

function isValid() 
{
    try {

        $url = 'https://www.google.com/recaptcha/api/siteverify';
        $data = ['secret'   => '[YOUR SECRET KEY]',
                 'response' => $_POST['g-recaptcha-response'],
                 'remoteip' => $_SERVER['REMOTE_ADDR']];
                 
        $options = [
            'http' => [
                'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
                'method'  => 'POST',
                'content' => http_build_query($data) 
            ]
        ];
    
        $context  = stream_context_create($options);
        $result = file_get_contents($url, false, $context);
        return json_decode($result)->success;
    }
    catch (Exception $e) {
        return null;
    }
}

数组语法:我使用“新”数组语法([]代替array(..))。如果您的php版本尚不支持此功能,则必须相应地编辑这3个数组定义(请参阅注释)。

返回值:true如果用户有效,false则该函数返回,否则返回null错误。您可以简单地通过编写来使用它if (isValid()) { ... }


2
如果您需要旧的数组语法,请将$data = ...$options = ...声明更改为:$data = array('secret' => '[YOUR SECRET KEY]', 'response' => $_POST['g-recaptcha-response'], 'remoteip' => $_SERVER['REMOTE_ADDR']); $options = array( 'http' => array( 'header' => "Content-type: application/x-www-form-urlencoded\r\n", 'method' => 'POST', 'content' => http_build_query($data) ) );
Levite 2015年

2
您可以将请求保存到服务器并提前保释:if (empty($_POST['g-recaptcha-response'])) { return false; }
Westy92 '16

6
https url实际上是加密的,因此即使使用GET请求也不会公开私钥,请参阅:stackoverflow.com/questions/499591/are-https-urls-encrypted
Varga Tamas

1
请注意,出于调试目的,您只能拨打isValid()一次电话。如果第二次调用,它将返回false。用回声语句很难找到
答案

没有函数使用抛出异常,因此try {} catch()是毫无意义的
chris

22

我不喜欢这些解决方案。我用这个代替:

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://www.google.com/recaptcha/api/siteverify");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
    'secret' => $privatekey,
    'response' => $_POST['g-recaptcha-response'],
    'remoteip' => $_SERVER['REMOTE_ADDR']
]);

$resp = json_decode(curl_exec($ch));
curl_close($ch);

if ($resp->success) {
    // Success
} else {
    // failure
}

我认为这是更好的选择,因为您可以确保将其发布到服务器中并且不会进行尴尬的“ file_get_contents”调用。这与此处所述的Recaptcha 2.0兼容:https : //developers.google.com/recaptcha/docs/verify

我找到这种清洁剂。当我觉得卷曲就足够时,我看到大多数解决方案都是file_get_contents。


2
如果由于在php.ini中禁用了“ allow_url_fopen”而无法使用file_get_contents(),这是一个很好的工作解决方案。为我工作。+1。
格雷戈里R.17年

简单明了,简单易用,并按照Google的要求使用POST
John Contarino

7

简便而最佳的解决方案如下。
index.html

<form action="submit.php" method="POST">
   <input type="text" name="name" value="" />
   <input type="text" name="email" value="" />
   <textarea type="text" name="message"></textarea>
   <div class="g-recaptcha" data-sitekey="Insert Your Site Key"></div>
   <input type="submit" name="submit" value="SUBMIT">
</form>

Submit.php

<?php
if(isset($_POST['submit']) && !empty($_POST['submit'])){
  if(isset($_POST['g-recaptcha-response']) && !empty($_POST['g-recaptcha-response'])){
    //your site secret key
    $secret = 'InsertSiteSecretKey';
    //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){
        //contact form submission code goes here

        $succMsg = 'Your contact request have submitted successfully.';
    }else{
        $errMsg = 'Robot verification failed, please try again.';
    }
  }else{
    $errMsg = 'Please click on the reCAPTCHA box.';
  }
}
?>

我从这里找到了此参考资料和完整教程-在PHP中使用新的Google reCAPTCHA


5

我喜欢Levit的答案并最终使用它。但我只是想指出,以防万一,对于新的reCAPTCHA,有一个官方的Google PHP库:https : //github.com/google/recaptcha

最新版本(目前为1.1.2)支持Composer,并包含一个示例,您可以运行该示例查看是否已正确配置了所有内容。

在下面,您可以看到此官方库随附的示例的一部分(为清晰起见,我做了一些小的修改):

// Make the call to verify the response and also pass the user's IP address
    $resp = $recaptcha->verify($_POST['g-recaptcha-response'], $_SERVER['REMOTE_ADDR']);

    if ($resp->isSuccess()) {
// If the response is a success, that's it!
        ?>
        <h2>Success!</h2>
        <p>That's it. Everything is working. Go integrate this into your real project.</p>
        <p><a href="https://stackoverflow.com/">Try again</a></p>
        <?php
    } else {
// If it's not successful, then one or more error codes will be returned.
        ?>
        <h2>Something went wrong</h2>
        <p>The following error was returned: <?php
            foreach ($resp->getErrorCodes() as $code) {
                echo '<tt>' , $code , '</tt> ';
            }
            ?></p>
        <p>Check the error code reference at <tt><a href="https://developers.google.com/recaptcha/docs/verify#error-code-reference">https://developers.google.com/recaptcha/docs/verify#error-code-reference</a></tt>.
        <p><strong>Note:</strong> Error code <tt>missing-input-response</tt> may mean the user just didn't complete the reCAPTCHA.</p>
        <p><a href="https://stackoverflow.com/">Try again</a></p>
    <?php
    }

希望它能帮助某人。


2

在上面的示例中。对我来说,这if($response.success==false)东西行不通。这是正确的PHP代码:

$url = 'https://www.google.com/recaptcha/api/siteverify';
$privatekey = "--your_key--";
$response = file_get_contents($url."?secret=".$privatekey."&response=".$_POST['g-recaptcha-response']."&remoteip=".$_SERVER['REMOTE_ADDR']);
$data = json_decode($response);

if (isset($data->success) AND $data->success==true) {
            // everything is ok!
} else {
            // spam
}

2
这是因为您没有将true第二个参数传递给json_decode。默认情况下,json_decode返回一个对象(jsOn),但是传递true将允许它返回一个数组。
柯蒂斯·马图恩

“在上面的示例中...”,请注意,StackExchange平台根据答案的投票等级对其进行排序。上面的示例显然不是您所指的示例。
尼古拉斯

1

在服务器端使用PHP进行验证。您需要考虑的两个最重要的事情。

1. $_POST['g-recaptcha-response']

2.$secretKey = '6LeycSQTAAAAAMM3AeG62pBslQZwBTwCbzeKt06V';

$verifydata = file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret='.$secretKey.'&response='.$_POST['g-recaptcha-response']);
        $response= json_decode($verifydata);

如果您获得$ verifydata true,那么您就完成了
有关更多信息,请查看
使用PHP的Google reCaptcha。仅两步集成


1

它与mattgen88类似,但我只修复了CURLOPT_HEADER,并重新定义了数组,使其可以在domain.com主机服务器中工作。这在我的xampp本地主机上不起作用。那些小错误但花了很长时间才弄清楚。此代码已在domain.com托管上进行了测试。

   $privatekey = 'your google captcha private key';

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, "https://www.google.com/recaptcha/api/siteverify");
    curl_setopt($ch, CURLOPT_HEADER, 'Content-Type: application/json');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, array(
        'secret' => $privatekey,
        'response' => $_POST['g-recaptcha-response'],
        'remoteip' => $_SERVER['REMOTE_ADDR']
    )
               );

    $resp = json_decode(curl_exec($ch));
    curl_close($ch);

    if ($resp->success) {
        // Success
        echo 'captcha';
    } else {
        // failure
        echo 'no captcha';
    }

1

这里有一个简单的例子。只要记住要提供来自Google API的secretKey和siteKey。

<?php
$siteKey = 'Provide element from google';
$secretKey = 'Provide element from google';

if($_POST['submit']){
    $username = $_POST['username'];
    $responseKey = $_POST['g-recaptcha-response'];
    $userIP = $_SERVER['REMOTE_ADDR'];
    $url = "https://www.google.com/recaptcha/api/siteverify?secret=$secretKey&response=$responseKey&remoteip=$userIP";
    $response = file_get_contents($url);
    $response = json_decode($response);
    if($response->success){
        echo "Verification is correct. Your name is $username";
    } else {
        echo "Verification failed";
    }
} ?>

<html>
<meta>
    <title>Google ReCaptcha</title>
</meta>
<body>
    <form action="index.php" method="post">
        <input type="text" name="username" placeholder="Write your name"/>
        <div class="g-recaptcha" data-sitekey="<?= $siteKey ?>"></div>
        <input type="submit" name="submit" value="send"/>
    </form>
    <script src='https://www.google.com/recaptcha/api.js'></script>
</body>


1

源教程链接

V2谷歌验证码

步骤1-前往Google reCAPTCHA

登录然后获取站点密钥秘密密钥

第2步-在此处下载PHP代码,并将src文件夹上传到您的服务器上。

步骤3-在您的form.php中使用以下代码

        <head>
            <title>FreakyJolly.com Google reCAPTCHA EXAMPLE form</title>
            <script src='https://www.google.com/recaptcha/api.js'></script>
        </head>

        <body>
            <?php

            require('src/autoload.php');

            $siteKey = '6LegPmIUAAAAADLwDmXXXXXXXyZAJVJXXXjN';
            $secret = '6LegPmIUAAAAAO3ZTXXXXXXXXJwQ66ngJ7AlP';

            $recaptcha = new \ReCaptcha\ReCaptcha($secret);

            $gRecaptchaResponse = $_POST['g-recaptcha-response']; //google captcha post data
            $remoteIp = $_SERVER['REMOTE_ADDR']; //to get user's ip

            $recaptchaErrors = ''; // blank varible to store error

            $resp = $recaptcha->verify($gRecaptchaResponse, $remoteIp); //method to verify captcha
            if ($resp->isSuccess()) {

               /******** 

                Add code to create User here when form submission is successful

               *****/

            } else {

                /****

                // This variable will have error when reCAPTCHA is not entered correctly.

                ****/

               $recaptchaErrors = $resp->getErrorCodes(); 
            }


            ?>
                <form autcomplete="off" class="form-createuser" name="create_user_form" action="" method="post">
                    <div class="panel periodic-login">
                        <div class="panel-body text-center">
                            <div class="form-group form-animate-text" style="margin-top:40px !important;">
                                <input type="text" autcomplete="off" class="form-text" name="new_user_name" required="">
                                <span class="bar"></span>
                                <label>Username</label>
                            </div>
                            <div class="form-group form-animate-text" style="margin-top:40px !important;">
                                <input type="text" autcomplete="off" class="form-text" name="new_phone_number" required="">
                                <span class="bar"></span>
                                <label>Phone</label>
                            </div>
                            <div class="form-group form-animate-text" style="margin-top:40px !important;">
                                <input type="password" autcomplete="off" class="form-text" name="new_user_password" required="">
                                <span class="bar"></span>
                                <label>Password</label>
                            </div>
                            <?php 
                                    if(isset($recaptchaErrors[0])){
                                        print('Error in Submitting Form. Please Enter reCAPTCHA AGAIN');
                                    }
                              ?>
                            <div class="g-recaptcha" data-sitekey="6LegPmIUAAAAADLwDmmVmXXXXXXXXXXXXXXjN"></div>
                            <input type="submit" class="btn col-md-12" value="Create User">
                        </div>
                    </div>
                </form>
        </body>

        </html>

0

响应@ mattgen88的回答,这是一种布局更好的CURL方法:

   //$secret= 'your google captcha private key';
    $curl = curl_init();
    curl_setopt_array($curl, array(
        CURLOPT_URL             => "https://www.google.com/recaptcha/api/siteverify",
        CURLOPT_HEADER          => "Content-Type: application/json",
        CURLOPT_RETURNTRANSFER  => true,
        CURLOPT_SSL_VERIFYPEER  => FALSE, // to disable ssl verifiction set to false else true
        //CURLOPT_ENCODING      => "",
        CURLOPT_MAXREDIRS       => 10,
        CURLOPT_TIMEOUT         => 30,
        CURLOPT_HTTP_VERSION    => CURL_HTTP_VERSION_1_1,
        CURLOPT_CUSTOMREQUEST   => "POST",
        CURLOPT_POSTFIELDS      => array(
            'secret' => $secret,
            'response' => $_POST['g-recaptcha-response'],
            'remoteip' => $_SERVER['REMOTE_ADDR']
        )
    ));

    $response = json_decode(curl_exec($curl));
    $err = curl_error($curl);

    curl_close($curl);

    if ($response->success) {
        echo 'captcha';
    } 
    else if ($err){
        echo $err;
    }   
    else {
        echo 'no captcha';
    }

0

检查下面的例子

<script src='https://www.google.com/recaptcha/api.js'></script>
<script>

function get_action(form) 
{
    var v = grecaptcha.getResponse();
    if(v.length == 0)
    {
        document.getElementById('captcha').innerHTML="You can't leave Captcha Code empty";
        return false;
    }
    else
    {
         document.getElementById('captcha').innerHTML="Captcha completed";
        return true; 
    }
}

</script>
<form autocomplete="off" method="post" action=submit.php">

    <input type="text" name="name">
    <input type="text" name="email">
    <div class="g-recaptcha" id="rcaptcha"  data-sitekey="site key"></div>
    <span id="captcha" style="color:red" /></span> <!-- this will show captcha errors -->
    <input type="submit" id="sbtBrn" value="Submit" name="sbt" class="btn btn-info contactBtn" />
</form>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.