MeltingDog
MeltingDog

Reputation: 15468

Recaptcha no longer working after update to checkbox style version

I am using the new version of Recaptcha - the one that has a check box instead of a text field.

However it doesnt work. Although the new Recaptcha appears, I just get the error page each time I check the box.

I've looked through the documentation and it doesnt mention any thing different than the old one about setting it up.

Ive downloaded the latest recaptchalib.php, added <script src='https://www.google.com/recaptcha/api.js'></script> in my header and have set up my server side script as such:

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

  if (!$resp->is_valid) {
    //CAPTCHA was entered incorrectly
    header( "Location: $error_page" );

    die ("The reCAPTCHA wasn't entered correctly. Go back and try it again." .
         "(reCAPTCHA said: " . $resp->error . ")");
  } else {
    //Successful verification

My client side seems fine, simply:

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

Of course, I've double checked the both keys and all my paths are correct.

Is there a new library I am meant to use or a different way of processing for the new check box type Recaptcha? Anything I am doing wrong?

Upvotes: 0

Views: 895

Answers (2)

Luke
Luke

Reputation: 5642

Yes, the "latest" recaptchalib.php hasn't been updated in years. Be sure to give the Google Doc a 1-star rating and they might do something about it. I went round and round in circles on this until I realised that the recaptchalib.php file was the problem.

This post explains how to use this recaptchalib.php without too much ado.

As you have already stated, on your page you need:

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

<form method="POST" action="/your-action-page.php">

    <!-- All your form fields here -->

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

    <input type="submit" value="Submit" />

</form>

Then in your-action-page.php you need the following:

<?php 

    require_once('path-to/recaptchalib.php');

    $secret = "yoursecretkey";  

    $response = null;

    $reCaptcha = new ReCaptcha($secret);


    if ($_POST["g-recaptcha-response"]) {

        $response = $reCaptcha->verifyResponse( $_SERVER["REMOTE_ADDR"],  $_POST["g-recaptcha-response"] ); 

    } 

    if ($response != null && $response->success) {  

        // Your code to handle a successful verification

    } 

    else {

        // What happens when the CAPTCHA is entered incorrectly

    }

?>

And don't forget to upload the alternative recaptchalib.php:

<?php

/**
* This is a PHP library that handles calling reCAPTCHA.
*    - Documentation and latest version
*          https://developers.google.com/recaptcha/docs/php
*    - Get a reCAPTCHA API Key
*          https://www.google.com/recaptcha/admin/create
*    - Discussion group
*          http://groups.google.com/group/recaptcha
*
* @copyright Copyright (c) 2014, Google Inc.
* @link      http://www.google.com/recaptcha
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

/**
* A ReCaptchaResponse is returned from checkAnswer().
*/

class ReCaptchaResponse {
    public $success;
    public $errorCodes;
}

class ReCaptcha {
    private static $_signupUrl = "https://www.google.com/recaptcha/admin";
    private static $_siteVerifyUrl =
    "https://www.google.com/recaptcha/api/siteverify?";
    private $_secret;
    private static $_version = "php_1.0";

    /**
     * Constructor.
     *
     * @param string $secret shared secret between site and ReCAPTCHA server.
     */

    function ReCaptcha($secret) {
        if ($secret == null || $secret == "") {
            die("To use reCAPTCHA you must get an API key from <a href='"
            . self::$_signupUrl . "'>" . self::$_signupUrl . "</a>");
        }
        $this->_secret=$secret;
    }

    /**
     * Encodes the given data into a query string format.
     *
     * @param array $data array of string elements to be encoded.
     *
     * @return string - encoded request.
     */

    private function _encodeQS($data) {
        $req = "";
        foreach ($data as $key => $value) {
        $req .= $key . '=' . urlencode(stripslashes($value)) . '&';
        }
        // Cut the last '&'
        $req=substr($req, 0, strlen($req)-1);
        return $req;
    }

    /**
     * Submits an HTTP GET to a reCAPTCHA server.
     *
     * @param string $path url path to recaptcha server.
     * @param array  $data array of parameters to be sent.
     *
     * @return array response
     */

    private function _submitHTTPGet($path, $data) {
        $req = $this->_encodeQS($data);
        $response = file_get_contents($path . $req);
        return $response;
    }

    /**
     * Calls the reCAPTCHA siteverify API to verify whether the user passes
     * CAPTCHA test.
     *
     * @param string $remoteIp   IP address of end user.
     * @param string $response   response string from recaptcha verification.
     *
     * @return ReCaptchaResponse
     */

    public function verifyResponse($remoteIp, $response) {
        // Discard empty solution submissions
        if ($response == null || strlen($response) == 0) {
            $recaptchaResponse = new ReCaptchaResponse();
            $recaptchaResponse->success = false;
            $recaptchaResponse->errorCodes = 'missing-input';
            return $recaptchaResponse;
        }
        $getResponse = $this->_submitHttpGet(
            self::$_siteVerifyUrl,
            array (
                'secret' => $this->_secret,
                'remoteip' => $remoteIp,
                'v' => self::$_version,
                'response' => $response
            )
        );
        $answers = json_decode($getResponse, true);
        $recaptchaResponse = new ReCaptchaResponse();
        if (trim($answers ['success']) == true) {
            $recaptchaResponse->success = true;
        }
        else {
            $recaptchaResponse->success = false;
            $recaptchaResponse->errorCodes = $answers [error-codes];
        }
        return $recaptchaResponse;
    }
}
?>

Hope that helps! :)

Upvotes: 0

Alexandru Guzinschi
Alexandru Guzinschi

Reputation: 5726

Are you absolutely sure that you included a recaptchalib.php that is using the new API ? Can you double check that ?

I'm asking this because I see that the latest version of recaptcha-php is 1.11, which was released in 2010 and I don't see any updates in their VCS either.

That library is using the old API:

$response = _recaptcha_http_post (RECAPTCHA_VERIFY_SERVER, "/recaptcha/api/verify",
    array (
         'privatekey' => $privkey,
         'remoteip' => $remoteip,
         'challenge' => $challenge,
         'response' => $response
         ) + $extra_params
    );

The new API should be called like:

https://www.google.com/recaptcha/api/siteverify?secret=your_secret&response=response_string&remoteip=user_ip_address

A simple implementation for a login form, could look like:

<form role="form" method="POST" action="/login_check.php">
   <input type="text" class="" id="username" placeholder="Enter username">
   <input type="password" class="" id="password">

   <div class="g-recaptcha" data-sitekey="[YOUR SITE KEY]"></div>
</form>

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

In login_check.php:

<?php

// Get yours from https://www.google.com/recaptcha/intro/index.html
$api_secret     = 'YOUR API SECRET';
$api_endpoint   = 'https://www.google.com/recaptcha/api/siteverify';

if ((strtoupper($_SERVER["REQUEST_METHOD"])) === "POST") {

    if (empty($_POST['g-recaptcha-response'])) {
        // The user did not complete reCAPTCHA
        header("location: index.php");
        exit;
    }

    $api_url    = sprintf('%s?secret=%s&response=%s&remoteip=%s', $api_endpoint, $api_secret, $_POST['g-recaptcha-response'], $_SERVER['REMOTE_ADDR']);
    $response   = json_decode(apiVerify($api_url), true);

    // reCAPTCHA is NOT correct.
    if (false === $response['success']) {
        // The user is not a human.
        header("location: index.php");
        exit;
    }

    // reCAPTCHA was correct, so you can go ahead and check login credentials ...

    echo "Welcome !";
}

function apiVerify($url)
{
    $curl = curl_init();

    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl, CURLOPT_TIMEOUT, 10);
    curl_setopt($curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.16) Gecko/20110319 Firefox/3.6.16");

    $data = curl_exec($curl);

    curl_close($curl);

    return $data;
}

You could (and should) extend this example in order to show some feedback to the user, perform some extra validation, etc, but I think that it should suffice in order to get you started.

Upvotes: 1

Related Questions