No CAPTCHA reCAPTCHA Integration with WordPress

A few weeks ago, the Google security team announced a new version of the popular reCAPTCHA system used by millions of websites in combating spam.

For years, reCAPTCHA has prompted users to confirm they aren’t robots by asking them to read distorted text to be entered into a box, like this:

The Old reCAPTCHA

A lot of people griped and faulted the old reCAPTCHA system for many reasons. The distorted text it produces is difficult to recognize and bots get past the test better than humans do.

The new CAPTCHA is easy and convenient. All you need to do is click on a checkbox and you’re done. It’s also pretty effective in combating spam.

The New "No CAPTCHA"

In this article, we will learn how to integrate the new No CAPTCHA reCAPTCHA with a custom form and WordPress.

reCAPTCHA Form Integration

Let’s go over the process on how to integrate reCAPTCHA with a web form.

First off, head over to reCAPTCHA to grab your site and secret key.

Displaying the CAPTCHA

Include the following to the header section of the web page: <script src="https://www.google.com/recaptcha/api.js" async defer></script>.

Add <div class="g-recaptcha" data-sitekey="your_site_key"></div> to wherever you want to output the CAPTCHA where your_site_key is your domain site/public key.

More information on configuring the display of the CAPTCHA widget can be found here.

Verifying the User’s Response

To verify the user response (check if the user passed or failed the CAPTCHA test), send a GET request to the URL below using either cURL, Guzzle, WordPress HTTP API or any HTTP client.

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

Where:

– your_secret: Secret (private) key.
– response_string: The user response token (retrieved via PHP by $_POST['g-recaptcha-response']) ).
– user_ip_address: The user IP address albeit optional. ($_SERVER["REMOTE_ADDR"]).

If the request was successfully sent, the response will be a JSON object similar to the one below.

1
2
3
{
  "success": true|false
}

Decode the response using json_decode() and grab success property $response['success'] which returns true if the user passes the test, or false otherwise.

More information on verifying the user response can be found here.

reCAPTCHA WordPress Integration

Having learned how the new No CAPTCHA reCAPTCHA can be integrated with a form, let’s also see how it can be integrated with WordPress.

The first step is to include the plugin file header:

1
2
3
4
5
6
7
8
9
10
11
<?php
 
/*
Plugin Name: No CAPTCHA reCAPTCHA
Description: Protect WordPress login, registration and comment form from spam with the new No CAPTCHA reCAPTCHA
Version: 1.0
Author: Agbonghama Collins
Author URI: http://w3guy.com
License: GPL2
*/

Enqueue the reCAPTCHA script to WordPress header section.

1
2
3
4
5
6
7
8
9
10
// add the header script to login/registration page header
add_action( 'login_enqueue_scripts', 'header_script' );
 
// add CAPTCHA header script to WordPress header
add_action( 'wp_head', 'header_script' );
 
/** reCAPTCHA header script */
function header_script() {
echo '<script src="https://www.google.com/recaptcha/api.js" async defer></script>';
}

Next we use display_captcha() and the captcha_verification() wrapper function for displaying the CAPTCHA widget and verifying the user response.

Note: change *your_site_key* and *your_secret* in the code below to your site (public) key and secret (private) key respectively.

1
2
3
4
/** Output the reCAPTCHA form field. */
function display_captcha() {
    echo '<div class="g-recaptcha" data-sitekey="your_site_key"></div>';
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
 * Send a GET request to verify CAPTCHA challenge
 *
 * @return bool
 */
function captcha_verification() {
 
    $response = isset( $_POST['g-recaptcha-response'] ) ? esc_attr( $_POST['g-recaptcha-response'] ) : '';
 
    $remote_ip = $_SERVER["REMOTE_ADDR"];
 
    // make a GET request to the Google reCAPTCHA Server
    $request = wp_remote_get(
        'https://www.google.com/recaptcha/api/siteverify?secret=your_secret&response=' . $response . '&remoteip=' . $remote_ip
    );
 
    // get the request response body
    $response_body = wp_remote_retrieve_body( $request );
 
    $result = json_decode( $response_body, true );
 
    return $result['success'];
}

We’ve now defined the base functionality of the plugin, up next is integrating the CAPTCHA with login, registration and comment forms.

Login Form

Include the CAPTCHA widget to the login form by hooking the function display_captcha() to thelogin_form Action.

1
2
// adds the CAPTCHA to the login form
add_action( 'login_form', array( __CLASS__, 'display_captcha' ) );

The validate_login_captcha() function will validate and ensure the CAPTCHA checkbox isn’t left unchecked and that the test is passed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// authenticate the CAPTCHA answer
add_action( 'wp_authenticate_user', 'validate_captcha', 10, 2 );
 
/**
 * Verify the CAPTCHA answer
 *
 * @param $user string login username
 * @param $password string login password
 *
 * @return WP_Error|WP_user
 */
function validate_captcha( $user, $password ) {
 
    if ( isset( $_POST['g-recaptcha-response'] ) && !captcha_verification() ) {
        return new WP_Error( 'empty_captcha', '<strong>ERROR</strong>: Please retry CAPTCHA' );
    }
 
    return $user;
}

Registration Form

Include the CAPTCHA widget to the registration form by hooking the function display_captcha() to theregister_form Action.

1
2
// adds the CAPTCHA to the registration form
add_action( 'register_form', 'display_captcha' );

Validate the CAPTCHA test in the registration form with the validate_captcha_registration_field()function hooked to registration_errors.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// authenticate the CAPTCHA answer
add_action( 'registration_errors', 'validate_captcha_registration_field', 10, 3 );
 
/**
 * Verify the captcha answer
 *
 * @param $user string login username
 * @param $password string login password
 *
 * @return WP_Error|WP_user
 */
function validate_captcha_registration_field( $errors, $sanitized_user_login, $user_email ) {
    if ( isset( $_POST['g-recaptcha-response'] ) && !captcha_verification() ) {
        $errors->add( 'failed_verification', '<strong>ERROR</strong>: Please retry CAPTCHA' );
    }
 
    return $errors;
}

Comment Form

First, create a global variable that will hold the status of the CAPTCHA test. That is, when a user fails the challenge, it is set to ‘failed’ and empty otherwise.

1
global $captcha_error;

Include the CAPTCHA widget to the comment form by hooking the display_captcha() function to thecomment_form Action.

1
2
// add the CAPTCHA to the comment form
add_action( 'comment_form', 'display_captcha' );

The filter preprocess_comment calls the validate_captcha_comment_field() function to ensure the CAPTCHA field isn’t left empty and also that the answer is correct.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// authenticate the captcha answer
add_filter( 'preprocess_comment', 'validate_captcha_comment_field');
 
/**
 * Verify the captcha answer
 *
 * @param $commentdata object comment object
 *
 * @return object
 */
function validate_captcha_comment_field( $commentdata ) {
    global $captcha_error;
    if ( isset( $_POST['g-recaptcha-response'] ) && ! (captcha_verification()) ) {
        $captcha_error = 'failed';
    }
 
    return $commentdata;
}

The filter comment_post_redirect calls redirect_fail_captcha_comment() to delete comments detected as spam and also adds some query parameters to the comment redirection URL.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
add_filter( 'comment_post_redirect', 'redirect_fail_captcha_comment', 10, 2 );
 
/**
 * Delete spam comments
 *
 * Add query string to the comment redirect location
 *
 * @param $location string location to redirect to after comment
 * @param $comment object comment object
 *
 * @return string
 */
function redirect_fail_captcha_comment( $location, $comment ) {
    global $captcha_error;
 
    if ( ! empty( $captcha_error ) ) {
 
        // delete the failed captcha comment
        wp_delete_comment( absint( $comment->comment_ID ) );
 
        // add failed query string for @parent::display_captcha to display error message
        $location = add_query_arg( 'captcha', 'failed', $location );
 
    }
 
    return $location;
}

Voila! We’re done coding the plugin.

Summary

In this article, we learned how to protect web forms against spam using the new No CAPTCHA reCAPTCHA and finally, integrated it with the WordPress login, registration and comment forms.

If you’d like to integrate the new reCAPTCHA widget with your WordPress powered site, the plugin is available at the WordPress plugin directory.

  • wordpress, captcha, recaptcha
  • 39 Users Found This Useful
這篇文章有幫助嗎?

相關文章

More Tips to Further Secure WordPress

WordPress has often been seen as the unofficial scapegoat to blame various security breaches on....

10 Tips to Secure WordPress

Keeping WordPress secure is important in order to ensure that your site isn’t compromised. Uptime...

Preventing Brute Force Attacks Against WordPress Websites

A ‘brute force’ login attack is a type of attack against a website to gain access to the site by...