Click here to Skip to main content
15,881,248 members
Articles / Web Development / ASP.NET

Custom reCaptcha Validation

Rate me:
Please Sign up or sign in to vote.
4.93/5 (22 votes)
15 Nov 2013CPOL2 min read 89.3K   3K   59   15
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:

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

Next, add the following code:

HTML
<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:

C#
// 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:

C#
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)


Written By
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.

Comments and Discussions

 
AnswerValidating Recapcha in asp.net Pin
Member 1019151312-May-14 3:08
professionalMember 1019151312-May-14 3:08 
QuestionA small change to your line of code worked for me...might help others Pin
Mikko-124-Feb-14 1:35
Mikko-124-Feb-14 1:35 
AnswerRe: A small change to your line of code worked for me...might help others Pin
Nathan St3-Mar-14 1:02
Nathan St3-Mar-14 1:02 
GeneralMy vote of 3 Pin
Member 1059688321-Feb-14 21:18
Member 1059688321-Feb-14 21:18 
ghghghghg
gh
GeneralMy vote of 5 Pin
csharpbd17-Sep-13 17:48
professionalcsharpbd17-Sep-13 17:48 
QuestionMan You are awesome! :) Thank You very much!! Pin
Rockie(aka Collapse Troll)2-Jul-13 3:01
Rockie(aka Collapse Troll)2-Jul-13 3:01 
QuestionEnglish language audio challenge Pin
dacku8716-Feb-11 22:42
dacku8716-Feb-11 22:42 
GeneralMy vote of 3 Pin
Andrey Mazoulnitsyn26-Jan-11 21:30
Andrey Mazoulnitsyn26-Jan-11 21:30 
GeneralRe: My vote of 3 Pin
Rockie(aka Collapse Troll)2-Jul-13 3:04
Rockie(aka Collapse Troll)2-Jul-13 3:04 
QuestionGood stuff Pin
Sike Mullivan7-Oct-10 3:58
Sike Mullivan7-Oct-10 3:58 
AnswerRe: Good stuff Pin
Sike Mullivan7-Oct-10 4:05
Sike Mullivan7-Oct-10 4:05 
GeneralRe: Good stuff Pin
Nathan St7-Oct-10 4:12
Nathan St7-Oct-10 4:12 
GeneralRe: Good stuff Pin
Sike Mullivan7-Oct-10 4:23
Sike Mullivan7-Oct-10 4:23 
GeneralRe: Good stuff Pin
shakil03040037-Oct-10 4:36
shakil03040037-Oct-10 4:36 
GeneralRe: Good stuff Pin
Nathan St7-Oct-10 4:48
Nathan St7-Oct-10 4:48 

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

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