How to implement Google reCAPTCHA on my website?

I'm trying to implement Google's reCAPTCHA on my site, and I can't do the Server-Side integration (I use the PHP language). How can I make reCAPTCHA work, and perform validation before submitting my form data?

Google reCAPTCHA source and documentation

Author: Jorge B., 2015-04-24

3 answers

ReCAPTCHA introduction

ReCAPTCHA is a new tool from Google to protect your website from spammers and bots. It comes from an innovative idea, since until then captchas were seen more as an obstacle than an auxiliary by users. With reCAPTCHA this is different, as all the user needs to do is click on a checkbox, confirming that it is not a robot. That way everyone wins, the user has faster access to the desired information, and you keeps unwanted visitors from your website.

Amazing! I want to have one of those, how do I do it?

The first step is you get a key to your website. Go to the site below and click on the blue button located in the top-right position of the site, written "Get reCAPTCHA": https://www.google.com/recaptcha/intro/index.html

After registering your site, you will have two important information at hand: the site key , and the secret (I'll call it the secret key). The first step to implementing reCAPTCHA on your site is to insert the API into your site. Enter the code inside your site's head tag:

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

All set for the next step.

Creating the form

Create a common form, I did with two fields: one for the user to put the name, and another for any message. The markup looked like this:

<h1>Exemplo de formulário com o reCaptcha</h1>
		
<form action="formulario.php" method="post">
  Digite seu nome: <input type="text" name="nome"><br><br>
  Deixe sua mensagem: <br>
  <textarea name="mensagem" rows="7" cols="35"></textarea><br><br>
  <input type="submit" value="Submit" name="formulario">
</form>

Entering reCAPTCHA in the form is extremely simple, you just need to add the following element in the position you want it to appear:

<div class="g-recaptcha" data-sitekey="SUA-CHAVE"></div>

Do not forget to replace your key with the key you received on the site, remembering that it is the key of the site , not the secret key !

Replace the property action in the tag form for the name of the PHP file that will validate the form. You can validate on the same page, but I preferred to leave on a separate one for the code to stay simpler.

But I can't validate using JavaScript right now?

No:) you will already understand the reason.

Creating PHP code to validate form

Let's get the value of the name field and the message that the user sent:

if (isset($_POST['nome'])) {
    $nome = $_POST['nome'];
}

if (isset($_POST['mensagem'])) {
    $mensagem = $_POST['mensagem'];
}

From here that captcha validation actually happens. It is sent to us via POST a value provided by reCAPTCHA, it is possible to retrieve this value by the variable $_POST['g-recaptcha-response']. Logo:

if (isset($_POST['g-recaptcha-response'])) {
    $captcha_data = $_POST['g-recaptcha-response'];
}

// Se nenhum valor foi recebido, o usuário não realizou o captcha
if (!$captcha_data) {
    echo "Por favor, confirme o captcha.";
    exit;
}

Looks like it's over, right? No! Now that comes the fun part, remember when I said it was necessary that the captcha had to go through a PHP validation? This is necessary because reCAPTCHA uses information in the Google database, which contains various information about the user who" performed " the captcha. In this way it is possible to distinguish an ordinary user from a bot. To validate the user, we need to make a request to the reCAPTCHA API, using the file_get_contents. Note:

$resposta = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=SUA-CHAVE-SECRETA&response=".$captcha_data."&remoteip=".$_SERVER['REMOTE_ADDR']);

Search the middle of the URL for your secret-key and replace it with yours. What this command does is retrieve data in the reCAPTCHA API for information about the values that were provided by the captcha, as well as sending the user'S IP for future evaluations.

With the request sent, we only need to treat the response:

if ($resposta.success) {
    echo "Obrigado por deixar sua mensagem!";
} else {
    echo "Usuário mal intencionado detectado. A mensagem não foi enviada.";
    exit;
}

I hope you have understood how the system works. Any questions already know, we are here to help. ;)

 54
Author: Rafael Almeida, 2018-07-06 10:54:45

FULLY REPHRASED ANSWER . Reason: I put the information as I found out and it was very bad. I thank Rafael Almeida, for the first answer, who helped me a lot and led me to discover more things. And to the administrators, who made changes that guided me to improve the response. My answer exists just to add information to the excellent work already done by Rafael Almeida.

Client-side code (HTML and JavaScript)

A question raised: but I can't validate using JavaScript right now?

Would even give to do, in fact, using AJAX: send the information to PHP and get the answer before submitting the entire form, with the rest of the fields. However, it does not seem like a necessary effort, since by clicking reCAPTCHA it does not release until the user gives the right answer. At least, I did not see anything happen other than with or without the brand "check " to indicate that everything is OK (for example, I did not see a red X in place). In other words, reCAPTCHA is all or nothing: either the user did not respond or answered and answered right.

Which seems useful here to do the check in JS before sending to PHP to know if the user at least used reCAPTCHA, to avoid sending the entire form. This is very easy, because the API already has the function, just put something like that in the function that performs in the onsubmit of the Form:

 if (grecaptcha.getResponse() == "")
 {
      alert("Você não clicou no reCAPTCHA, por favor, faça!")
      return false;
 }

Server-side code (PHP)

What prompted me to get more information is that the code with file_get_contents Didn't work out for me. Initially, I thought the problem was the function's send method (GET, while reCAPTCHA's website says it needs to be POST). Then I found that it works perfectly on the copy of the site hosted on my PC. That is, it is the hosting server (I use Hostmedia) that blocks. I still tried, but without success :

ini_set('allow_url_fopen', 1)

The alternative answer, based on cURL, can be useful for those who have the site on the same or another hosting that also blocks. In any case, it may be interesting to avoid that, in case of warning , the URL including the Secret Key will not be registered in the log. Follow the code:

# Os parâmetros podem ficar em um array
$vetParametros = array (
    "secret" => "SUA-CHAVE-SECRETA",
    "response" => $_POST["g-recaptcha-response"],
    "remoteip" => $_SERVER["REMOTE_ADDR"]
);
# Abre a conexão e informa os parâmetros: URL, método POST, parâmetros e retorno numa string
$curlReCaptcha = curl_init();
curl_setopt($curlReCaptcha, CURLOPT_URL,"https://www.google.com/recaptcha/api/siteverify");
curl_setopt($curlReCaptcha, CURLOPT_POST, true);
curl_setopt($curlReCaptcha, CURLOPT_POSTFIELDS, http_build_query($vetParametros));
curl_setopt($curlReCaptcha, CURLOPT_RETURNTRANSFER, true);
# A resposta é um objeto json em uma string, então só decodificar em um array (true no 2º parâmetro)
$vetResposta = json_decode(curl_exec($curlReCaptcha), true);
# Fecha a conexão
curl_close($curlReCaptcha);
# Analisa o resultado (no caso de erro, pode informar os códigos)
if ($vetResposta["success"]) echo "<p>Captcha OK!</p>\n";
else 
{
    echo "$<p>Problemas:</p>\n";
    foreach ($vetResposta["error-codes"] as $strErro) echo "$strTab<p>Erro: $strErro</p>\n";
}

A little more, still on the server side...

If you look at the instructions on the reCAPTCHA website, there is an indication of a library that is on github, at / google / recaptcha. It also works well: it was enough to put the src folder of the downloaded ZIP somewhere on the site and use the code similar to their example. The only problem is that it was giving the following error:

Invalid-json

Then I found tip in another Stackoverflow article (method indication CurlPost):

$recaptcha = new \ReCaptcha\ReCaptcha($secret, new \ReCaptcha\RequestMethod\CurlPost());
$resp = $recaptcha->verify($gRecaptchaResponse, $remoteIp);
if ($resp->isSuccess()) {
    // verified!
} else {
    $errors = $resp->getErrorCodes();
}

For this, I did not test whether the problem was in the hosting or in the library class itself.


 16
Author: Binho RbSoft, 2015-12-14 10:59:23

Follows a complete implementation of reCaptcha that I am using on a site that I am developing, the only thing that is missing to work 100% is to create the objects, but I left well described how to create them, I am only a student so I did the best I could.

<?php ini_set('display_errors',1); ini_set('display_startup_erros',1); error_reporting(E_ALL); ?><!--Força o php a mostrar todo tipo de erro, linha temporária-->
    <?php
    function __autoload($class_name){
        require_once '../_lib/'.$class_name.'.php';//-->lê minhas classes de forma automática
    }
    ?>
    <!DOCTYPE html>
    <html>
    <head>
        <link rel="stylesheet" type="text/css" href="_css/login.css"/>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
        <script src='https://www.google.com/recaptcha/api.js'></script>
        <script>
            $(document).ready(function() {
                $('#send').prop('disabled', true);//desativa o botão enviar
                $('.g-recaptcha').hide();//esconde o captcha
                validate();
                $('#inputEmail, #inputPassword').change(validate);
            });
            function validate() {
                if ($('#inputEmail').val().length > 10) {//enquanto o campo de email nao tiver menos que 10 caracteres, não ativa o reCaptcha
                    $('.g-recaptcha').show();//exibe o reCaptcha
                }else{//se mudar de ideia e reduzir o campo pra menos de 10 caracteres...
                    $('.g-recaptcha').hide();//o reCaptcha se esconde novmanete
                }
            }
            function enableSend() {
                $('#send').prop('disabled', false);//quando o captcha é confirmado, ativa o botao enviar
            }
        </script>
    </head>

    <body>
    <?php
    $helper = new Helpers();//-->objeto com vários métodos importantes
    if (isset($_POST['attempt'])){//verifica se tem tentativa restante
        $attempt = intval($helper->validation($_POST['attempt']));//validation=método que verifica e escapa minha sring (trim(), stripcslashes() e htmlspecialchars())
    }else{
        $attempt = 3;//se não for definido número de tentativas, aqui é definido como 3
    }

    if (isset($_POST['g-recaptcha-response']) and isset($_POST['username']) and isset($_POST['password'])) {//garante que todos os campos foram preenchidos
        $captcha_data = $_POST['g-recaptcha-response'];
        if ($captcha_data) {//Verificação do reCaptcha
            $resposta = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=DIGITE-SUA-CHAVE-SECRETA-GERADA-PELO-GOOGLE-AQUI=" . $captcha_data . "&remoteip=" . $_SERVER['REMOTE_ADDR']);
            if ($resposta) {//validação do reCaptcha
                $username = strtolower($helper->validation($_POST['username']));
                $password = $helper->validation($_POST['password']);
                $user = new User();//--->meu objeto que acessa o banco de dados usando PDO
                $userValidated = $user->checkPasswordHash($username);//--->método do meu objeto que procura o usuario no bacno de dados (SELECT * FROM tbl_Users WHERE username = $username)
                if ($userValidated){//verifica se o email existe, se existir...
                    if ($userValidated->status == 1){//verifica se a conta está bloqueada ou não
                        echo 'Essa conta está bloqueada, criar botão para reenviar o email de recuperação...';
                    }else{
                    $hash = $userValidated->password;//retorna o hash do password
                    if (password_verify($password, $hash)) {//compara a senha e o hash que foi criado usando password_hash() e salvo no banco de dados
                        echo 'Password é válido, inserir código que inicia as sessões e chama a próxima página';//-->insira seu código
                    } else {//caso o password estjeja errado, perde uma tentativa
                        if ($attempt != 1){//se a tentativa restante for igual a 1, a proxima vez será direcionado para a página de recuperação de senha
                            $attempt--;
                            echo 'Usuário e senha não combinam, você tem mais '.$attempt.' tentativas';//mostra o número de tentativas restante
                        }else{//bloqueia a conta e chama a página de recuperação de senha
                            echo 'inserir código que bloqueia a conta e abre pagina de recuperaçao de senha';//-->insira seu código de bloqueio
                        }
                    }
                    }
                }else{//se o email não existir, perde uma tentativa mas não avisa se o erro foi no email ou na senha
                    if ($attempt != 0){
                        $attempt--;
                        echo 'Usuário e senha não combinam, você tem mais '.$attempt.' tentativas';//mostra o número de tentativas restante
                    }else{//bloqueia a conta e chama a página de recuperação de senha
                        echo 'inserir código que bloqueia a conta e abre pagina de recuperaçao de senha';//-->insira seu código de bloqueio
                    }
                }
            } else {
                echo "Validação não concluída, tente novamente.";
                exit;
            }
        } else {
            echo "Validação não concluída, tente novamente.";
            exit;
        }
    }
    ?>
    <section>
        <form class="login" action="login.php" method="post">
            <fieldset>
                <legend>Login</legend>
                <label for="inputEmail" class="Label">Email: </label>
                <input id="inputEmail" class="inputText" type="email" maxlength="30" name="username" required>
                <label for="inputPassword" class="Label">Password: </label>
                <input id="inputPassword" class="inputPassword" type="password" maxlength="20" name="password" required>
                <div class="g-recaptcha" data-sitekey="DIGITE-A-CHAVE-DO-SEU-SITE-CRIADA-PELO-GOOGLE-AQUI" data-callback="enableSend"></div><!--Linha que adiciona o recaptcha-->
                <input type="hidden" name="attempt" value=<?php echo $attempt ?> /><!--envia por post o numero de tentativas restante-->
                <input type="submit" value="Confirmar" id="send" class="send">
            </fieldset>
        </form>
    </section>

    </body>
    </html>
 0
Author: Rimom Aguiar, 2016-08-09 04:08:16