Attack of the Bots! – Stop Them With ReCAPTCHA in ASP.NET MVC
As developers sometimes we forget that there are bad people out there. Nefarious people waiting for you to mess up, just so they can exploit your weaknesses. One of the biggest problems with the internet
today is the use of bots. If you have ever run a publicly open site like a blog, forum, or contact form then you know what I mean. You get flooded with junk that you didn’t even know existed. This can be a huge problem, because it essentially makes the data coming in hard if not impossible to sort. So how do you stop these advanced monsters from reeking havoc on your public facing site?
We first have to understand how they exploit your site. You probably have some kind of form on your site. It is there for anyone and everyone to use, just like you intended. You spent hours meticulously crafting this form with valid HTML and readable labels. There is your first problem. Bots traverse your page looking for FORM tags. Then they proceed to look for INPUT tags which match their criteria. If you use a popular CMS or Blogging engine then you are already at a disadvantage. These systems are known by bots and there are no surprises on how your system works. Then the bots proceeds to submit the form. All this occurs in a matter of nanoseconds. Remember computers are fast, even when they are evil. Now the bots have a choice, leave your defenseless site in search of another or proceed to submit your form mercilessly until your site collapses and your inbox is filled with worthless junk.
The popular solution to combating bots has been CAPTCHA systems. CAPTCHA stands for “Completely Automated Public Turing test to tell Computers and Humans Apart.” It usually involves a challenge-response test. The most popular kind is to show scrambled words in an image, which can be seen below. Some CAPTCHA systems can also get very strange. I have seen one that shows you screenshots of cute fuzzy animals and asks you to pick the kitten. This really is a interesting subject and I suggest you read the Wikipedia page on CAPTCHA.

Let’s get started in developing a solution. You might be thinking to yourself, “I don’t want to write a crazy CAPTCHA system.” Well you are in luck, there are several services on the internet that let you utilize their system. My favorite service is ReCAPTCHA. It offers both image based CAPTCHA tests along with audio tests for better accessibility. Let me show you what the final product will be like. I will be using the ASP.NET MVC sample project and modifying the registration page to add CAPTCHA checking. Dilled Fresno!?!? What the heck is that?

Step 1 – Getting Your ReCAPTCHA account.
Go to the ReCAPTCHA site and sign up for your keys. You will get a private key and and a public key. Copy these to notepad, you will need them.
Step 2 – Download the .Net Library for ReCAPTCHA
You will need to download the ReCAPTCHA .NET Library. Technically you don’t need this, you could write your own wrapper, but this makes it much easier. Go ahead and add this to your ASP.NET MVC project as a reference.
Step 3 – Implement the Client-Side
You want the ReCAPTCHA red box to show up on your site. So we are going to have to put some code in your view. ReCAPTCHA has already provided this code for for you. I have placed it below for faster access. Place this code within your Form tag, it is critical that you do so. Ok you are done. I also placed a ValidationMessage underneath the ReCAPTCHA code so that I could see my message.
<script type="text/javascript"
src="http://api.recaptcha.net/challenge?k=<YOUR PUBLIC KEY>">
</script>
<noscript>
<iframe src="http://api.recaptcha.net/noscript?k=<YOUR PUBLIC KEY>"
height="300" width="500" frameborder="0"></iframe><br>
<textarea name="recaptcha_challenge_field" rows="3" cols="40">
</textarea>
<input type="hidden" name="recaptcha_response_field"
value="manual_challenge">
</noscript>
<%= Html.ValidationMessage("ReCaptcha") %>
Step 4 – Implement the Server-Side
When the form is submitted, there will be two extra inputs submitted to your controller action. The “recaptcha_response_field” value and the “recaptcha_challenge_field” value. We will be using these to verify that the user is really human. So for the code that performs the CAPTCHA.
private bool PerformRecaptcha()
{
var validator = new RecaptchaValidator
{
PrivateKey = "<YOUR PRIVATE KEY>",
RemoteIP = Request.UserHostAddress,
Response = Request.Form["recaptcha_response_field"],
Challenge = Request.Form["recaptcha_challenge_field"]
};
try
{
var validationResult = validator.Validate();
if (validationResult.ErrorCode == "incorrect-captcha-sol")
ModelState.AddModelError("ReCaptcha", string.Format("Please retry the ReCaptcha portion again."));
return validationResult.IsValid;
}
catch (Exception e)
{
ModelState.AddModelError("ReCaptcha", "an error occured with ReCaptcha please consult documentation.");
return false;
}
}
RecaptchaValidator is from the assembly you referenced. Notice that we need to set the private key, and that we are getting the user’s I.P. address. We also set the fields that we got from the form. Now we just need to ask the service if everything is ok. The rest is trivial ASP.NET MVC code.
Conclusion
You can get ReCAPTCHA into your site in about 5 minutes, but it might take some time to perfect how you want it to integrate with you current scheme. For me, I don’t make a call to ReCAPTCHA if my model is not valid (see code below), this saves me an expensive and unnecessary internet call. I am also considering placing similar code in an ActionFilter, in the same fashion as ValidateAntiForgeryTokenAttribute. It should be pretty simple to do that.
if (ModelState.IsValid && PerformRecaptcha())
{
...
}
So now you have the power to stop those evil bots and take bake your site. Hope this helps.

January 2, 2010 - 9:35 pm
although im not using MVC, just normal form POST and jquery, your article helped me alot. thanks
January 2, 2010 - 9:57 pm
Thanks! That’s what I like to hear.
July 3, 2010 - 6:29 pm
Freakin hilarious irony. Comment number #3 above is actually common comment-spam bot text! Right down to the misspelling!
Traditional captcha isn’t the way people, don’t waste your time, they’re are already several frequently updated captcha breaking web services out there that are quite cheap and very effective. So annoying your users (the MS way!), isn’t really effective.
Better to just put a small script that randomly generates two random numbers and then ask the user to add them together and then have your from handler verify this for correctness.
Technically this is still a “Completely Automated Public Turing test to tell Computers and Humans Apart” system. Except it works and annoys people much much less.
This, BTW is only one of the truly endless amount of alternatives to traditional Captcha systems. Use your imagination and come up with your own. Why let (non Search Engine), bots onto your website in the first place, for instance?
July 3, 2010 - 7:02 pm
I guess I see you point texxs. I definitely am not in the business of web development to annoy my users, and certain captcha systems can be more than annoying.
To say that annoying users is the MS way is an unfair characterization of all MS developers. I have certainly been on my fair share of annoying PHP, Flash, and RoR sites and I’m sure you have been too. In addition, Google and Yahoo have been using the captcha idea on a majority of their forms for as long as I can remember.
Thank you and I appreciate the comment.
July 25, 2010 - 6:22 pm
Predictably it got stripped
Replace all [] angle equivalents:
namespace Common
{
public class ReCaptcha
{
public const string PublicKey = “[YOUR PUBLIC KEY]“;
}
// Usage: [%: Html.ReCaptcha() %]
public static class ReCaptchaExtensions
{
public static HtmlString ReCaptcha(this HtmlHelper html)
{
return new HtmlString(
“[script src='http://api.recaptcha.net/challenge?k=" + Common.ReCaptcha.PublicKey + "' type='text/javascript'][/script]” +
string.Format(“[noscript][iframe src='http://api.recaptcha.net/noscript?k={0}' height='300' width='500' frameborder='0'][/iframe][br /][textarea name='recaptcha_challenge_field' rows='3' cols='40'][/textarea][input type='hidden' name='recaptcha_response_field' value='manual_challenge'][/noscript]“,
Common.ReCaptcha.PublicKey));
}
}
}
July 26, 2010 - 7:00 am
That’s pretty cool. I always feel a little icky when putting HTML in code like this, but in this case it doesn’t feel that bad. Thank you.
July 26, 2010 - 9:22 am
You’re right, Khalid. I sound like a troll!
I too have seen many an irritating flash app, and yes some irritating PHP apps.
I have developed projects successfully using ASP.NET and it was the best choice for those projects.
And sorry, but I just LOVE irony! Hopefully it won’t come back to work against me in the future!