How to use Google reCaptcha
Matthew Martin
12/16/2014 01:04:00 PM
Tweetable
To start, you need an aspx page containing your web form. I'll assume that you already know the basics of how to make an aspx web form(in Visual Studio, most likely), set up event handlers, do postbacks, etc from the code-behind. I won't assume anything more than a beginner's understanding of these, but if none of that sounds familiar, you need to start with an asp.net tutorial instead of what follows. Also, I'm doing this all in Visual Studio 2010 with C#. So our aspx page code looks like this: The idea with this form is that users will type something in (an email message, for example), click submit, and then you can do something with that user input on the server side (send it as an email to someone, perhaps, or maybe save the text into a database).
The problem is that this form is accessible to both humans (good) and spambots (bad), so we need to add a reCaptcha to prevent spammers from being able to programmatically use these controls. To do that, you first need to go to google to get set up with reCaptcha. It is a free service, but you need to create an account and get three things: a script tag that looks like this:
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<div class="g-recaptcha" data-sitekey="your_site_key"></div>
The code behind has a Page_Load event handler by default. We won't be using it. Below it, we'll add three functions: one of them is the myFunction that is being called when the Submit button is clicked, and the other two will get the users' IP address and check to see if the reCaptcha validated, respectively. Additionally, we will be adding three using statements to the top: two are for System.Net and System.IO respectively, which are part of the standard library, and the third is Recaptcha which is not. You'll need to download the Recaptcha library here, extract it from the zip file, and add a reference to the library from your IDE, which is different than just adding the using statement (in Visual Studio, in the Solution Explorer right click References, then click Add Reference, go to the Browse tab, and point it to the location of the file you just downloaded.) So we have a code behind skeleton that looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Recaptcha;
using System.Net;
using System.IO;
namespace emailApp
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
bool reCaptchaValidate(string ipAddress)
{
bool Valid = false;
return Valid;
}
string getIpAddress()
{
}
protected void myFunction(object sender, EventArgs e)
{
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Recaptcha;
using System.Net;
using System.IO;
namespace emailApp
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
bool reCaptchaValidate(string ipAddress)
{
bool Valid = false;
return Valid;
}
string getIpAddress()
{
}
protected void myFunction(object sender, EventArgs e)
{
}
}
}
string getIpAddress()
{
System.Web.HttpContext context = System.Web.HttpContext.Current;
string ipAddress = context.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (!string.IsNullOrEmpty(ipAddress))
{
string[] addresses = ipAddress.Split(',');
if (addresses.Length != 0)
{
return addresses[0];
}
}
return context.Request.ServerVariables["REMOTE_ADDR"];
}
{
System.Web.HttpContext context = System.Web.HttpContext.Current;
string ipAddress = context.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (!string.IsNullOrEmpty(ipAddress))
{
string[] addresses = ipAddress.Split(',');
if (addresses.Length != 0)
{
return addresses[0];
}
}
return context.Request.ServerVariables["REMOTE_ADDR"];
}
Next, we fill in the method that will check the reCaptcha to see if the user passed the test. It is as follows:
public bool reCaptchaValidate(string ipAddress)
{
bool Valid = false;
string Response = Request["g-recaptcha-response"];//Getting Response String Append to Post Method
string url = @"https://www.google.com/recaptcha/api/siteverify?secret=your_site_key&response=" + Response + @"&remoteip=" + ipAddress;
//Request to Google Server
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
try
{
//Google recaptcha Response
using (WebResponse wResponse = req.GetResponse())
{
using (StreamReader readStream = new StreamReader(wResponse.GetResponseStream()))
{
string jsonResponse = readStream.ReadToEnd();
if (jsonResponse.Substring(15, 4) == "true")
{
Valid = true;
}
}
}
return Valid;
}
{
bool Valid = false;
string Response = Request["g-recaptcha-response"];//Getting Response String Append to Post Method
string url = @"https://www.google.com/recaptcha/api/siteverify?secret=your_site_key&response=" + Response + @"&remoteip=" + ipAddress;
//Request to Google Server
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
try
{
//Google recaptcha Response
using (WebResponse wResponse = req.GetResponse())
{
using (StreamReader readStream = new StreamReader(wResponse.GetResponseStream()))
{
string jsonResponse = readStream.ReadToEnd();
if (jsonResponse.Substring(15, 4) == "true")
{
Valid = true;
}
}
}
return Valid;
}
The next statement after the URL in our function preps an http request with the URL we've specified, and the GetResponse() will fire off our request and return the server's reply as a WebResponse object. We use the StreamReader to parse a string out of the WebResponse reply. The using() syntax isn't totally necessary, and neither is the try{}catch{} syntax. This extra verbiage is just in there to minimize and deal with potential errors, which may or may not be an issue depending how your application works. The response string will be formatted as a json object, like so:
{ "success": true|false, "error-codes": [...] // optional }
But so far, our webform does nothing. That's because the we've not put anything into the myFunction method, and thus nether of the methods above are being called. So here's how we do that:
protected void myFunction(object sender, EventArgs e)
{
if (reCaptchaValidate(getIpAddress()))
{
string userInput=Server.HtmlEncode(TextBox1.Text);
//do some stuff with userInput
}
}
{
if (reCaptchaValidate(getIpAddress()))
{
string userInput=Server.HtmlEncode(TextBox1.Text);
//do some stuff with userInput
}
}