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:
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:
Config.PublicKey
(This is your public reCaptcha key - if you don't have one, then head over here to get one.)
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:
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, Request.UserHostAddress,
Config.PrivateKey,
challenge,
clientResponse);
e.IsValid = validator.Validate();
if (!e.IsValid)
{
if (validator.IsErrored)
{
if (validator.Exception != null) Outcome.Text = validator.Exception.ToString();
else if (validator.ValidationResult != null) 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.