Click here to Skip to main content
Click here to Skip to main content
Go to top

Custom reCaptcha Validation

, 15 Nov 2013
Rate this:
Please Sign up or sign in to vote.
How to manually integrate reCaptcha into your site

Introduction

reCaptcha is a very useful Captcha tool to verify that a visitor to your site is indeed human. This is mainly useful for preventing spam.

Here's a sample reCaptcha:

a sample captcha

There are many custom Captcha solutions available on CodeProject, but reCaptcha has a number of advantages:

  • It's maintained by Google - so if the captcha images are compromised, an update from Google will resolve the problem without any work from the web developer.
  • Answers to reCAPTCHA challenges are used to digitize textual documents.
  • Your web server doesn't have to spend processor time producing captcha images.
  • reCaptcha has an audio option which is useful for visually impaired users.

These points are good, unless you're not a fan of Google.

Background

While working on a new feature for my website, I had some problems implementing reCaptcha.

There is a .NET server control provided, however, I couldn't get the client-side script to pick up the theme I wanted to use, so I decided to tough it out and implement it myself.

Using the Code

Note - reCaptcha requires you to create cryptographic keys. These are used to improve security and are easy to create - just click here to create your keys and then add your keys to the web.config of the demo.

First, we need to set up the client-side.

Include the reCaptcha client library in the header of your page:

<head>
    <script type="text/javascript" src="http://www.google.com/recaptcha/api/js/recaptcha_ajax.js">
    </script>
</head>     

Next, add the following code:

<div id="recaptcha_div"></div>
<script type="text/javascript">
    Recaptcha.create("<%=Config.PublicKey %>",
        "recaptcha_div", {
        lang: "<%=LanguageCode %>",
        theme: "clean",
        callback: Recaptcha.focus_response_field
    });
</script>

As you can see, we're taking two values from the server and injecting them directly into the client:

  1. Config.PublicKey (This is your public reCaptcha key - if you don't have one, then head over here to get one.)
  2. LanguageCode

If you want to change the theme used by the captcha, you can read more here.

Next, the server-side code.

The article download includes the full server-side code, here I will just outline the important parts.

Add a custom validator to your page and provide the following code as its server validation method:

// our custom server validator's validation method
protected void OnRecaptchaValidate(object sender, ServerValidateEventArgs e)
{
    string challenge = Request.Form["recaptcha_challenge_field"];
    string clientResponse = Request.Form["recaptcha_response_field"];
    
    reCaptchaValidation validator = 
        new reCaptchaValidation(
                    Config.Proxy,       // if you don't require a proxy to access 
                // the internet, just comment out this line.
                    Request.UserHostAddress, 
                    Config.PrivateKey, 
                    challenge, 
                    clientResponse);
                    
    e.IsValid = validator.Validate();
    
    if (!e.IsValid)
    {
        if (validator.IsErrored)
        {
            // oh dear, something not right
            
            if (validator.Exception != null)        // an exception occurred while 
                        // trying to validate
                Outcome.Text = validator.Exception.ToString();
            else if (validator.ValidationResult != null)  // the validation web service 
                        // returned an error code 
                    // (other than an invalid captcha solution)
                Outcome.Text = "web service error: " + validator.ValidationResult;
        }
    }
}

The validation is wrapped in a class called reCaptchaValidation:

public class reCaptchaValidation
{
    private string challenge, response, privateKey, ip;
    private IWebProxy proxy;

    public reCaptchaValidation(string clientIP, string privateKey, 
    string challenge, string response) : this(null, clientIP, privateKey, 
    challenge, response) { }

    public reCaptchaValidation(IWebProxy proxy, string clientIP, 
        string privateKey, string challenge, string response)
    {
        this.proxy = proxy;
        this.ip = clientIP;
        this.privateKey = privateKey;
        this.challenge = challenge;
        this.response = response;
    }

    private bool _errored;
    public bool IsErrored
    {
        get
        {
            return _errored;
        }
    }

    private Exception _ex;
    public Exception Exception
    {
        get
        {
            return _ex;
        }
    }

    private string _vr;
    public string ValidationResult
    {
        get
        {
            return _vr;
        }
    }

    public bool Validate()
    {
        try
        {
            string post = "privatekey=" + HttpUtility.UrlEncode(privateKey) + 
        "&remoteip=" + HttpUtility.UrlEncode(ip) + "&challenge=" + 
        HttpUtility.UrlEncode(challenge) + "&response=" + 
        HttpUtility.UrlEncode(response);

            WebRequest wr = HttpWebRequest.Create
            ("http://www.google.com/recaptcha/api/verify");
            wr.Method = "POST";

            if (proxy != null)
                wr.Proxy = proxy;

            wr.ContentLength = post.Length;
            wr.ContentType = "application/x-www-form-urlencoded";
            using (StreamWriter sw = new StreamWriter(wr.GetRequestStream()))
            {
                sw.Write(post);
                sw.Close();
            }

            HttpWebResponse resp = (HttpWebResponse)wr.GetResponse();
            using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
            {
                string valid = sr.ReadLine();
                if (valid != null)
                {
                    if (valid.ToLower().Trim() == "false")
                    {
                        string errorcode = sr.ReadLine();

                        if (errorcode != null)
                        {
                            if (errorcode.ToLower().Trim() != "incorrect-captcha-sol")
                            {
                                _vr = errorcode;
                                _errored = true;
                                return false;
                            }
                        }
                    }

                    return (valid.ToLower().Trim() == "true");
                }
                else _vr = "empty web service response";

                sr.Close();
                return false;
            }
        }
        catch (Exception caught)
        {
            _errored = true;
            _ex = caught;
        }
        return false;
    }
}

This class handles the validation of the user's captcha response by posting all the required information to the Google recaptcha validation web service.

I've made the demo web application as simple to use as possible - just supply the required values in the web.config.

History

  • 7th October, 2010: Published.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Nathan Staudt
Web Developer
United Kingdom United Kingdom
I've been a web application developer since the late 1990s, working for eCommerce, media and telecoms companies across europe and america.
 
I have a BSc (Hons) in computing from Middlesex University and took a few MCP exams several years ago too.
 
Born in America, I grew up in Ireland. My father encouraged my interest in computers as a child when he would bring home his "portable" ibm pc... (20kg or something like that) and I first wrote some stuff in QBasic aged seven or eight, but my real interest in computers took off when my family got internet access at home in the early 90s.
 
Feel free to email me Smile | :)

Comments and Discussions

 
AnswerValidating Recapcha in asp.net PinprofessionalMember 1019151312-May-14 3:08 
QuestionA small change to your line of code worked for me...might help others PinmemberMikko-124-Feb-14 1:35 
AnswerRe: A small change to your line of code worked for me...might help others PinmemberNathan Staudt3-Mar-14 1:02 
GeneralMy vote of 3 PinmemberMember 1059688321-Feb-14 21:18 
GeneralMy vote of 5 Pinmembercsharpbd17-Sep-13 17:48 
QuestionMan You are awesome! :) Thank You very much!! PinmemberRockie(aka Collapse Troll)2-Jul-13 3:01 
QuestionEnglish language audio challenge Pinmemberdacku8716-Feb-11 22:42 
I have impletemented the same and have checked the same code but audio is playing some garbage with back ground voice. unrecognizable audio voice.
 
can you please give me some details how to recognize this ? or which format its using to play ?
dacku

GeneralMy vote of 3 [modified] PinmemberAndrey Mazoulnitsyn26-Jan-11 21:30 
GeneralRe: My vote of 3 PinmemberRockie(aka Collapse Troll)2-Jul-13 3:04 
QuestionGood stuff PinmemberSike Mullivan7-Oct-10 3:58 
AnswerRe: Good stuff PinmemberSike Mullivan7-Oct-10 4:05 
GeneralRe: Good stuff PinmemberNathan Staudt7-Oct-10 4:12 
GeneralRe: Good stuff PinmemberSike Mullivan7-Oct-10 4:23 
GeneralRe: Good stuff Pinmembershakil03040037-Oct-10 4:36 
GeneralRe: Good stuff PinmemberNathan Staudt7-Oct-10 4:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140916.1 | Last Updated 15 Nov 2013
Article Copyright 2010 by Nathan Staudt
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid