.NET Blog

Tony Cavaliere

 
My Favourite Albums
  And the Grappa wins.
E-mail me Send mail
Add to Technorati Favorites AddThis Feed Button

Subscribe to Cynot Why Not


Recent posts

Disclaimer

Hey unlike other bloggers I stand by what I say but just in case. The opinions expressed herein are my own except on Tuesday when the second card is not turned up otherwise it ain't worth squat.

© Copyright 2010

Adding client side reCAPTCHA to your ASP.NET site

CAPTCHA is a challenge-response test to make sure that the user is human rather than some hacker automated software. The user is presented with a graphical image of some text and is required to type the text. If the user’s response is correct then all is well.

reCAPTCHA is unique in that user’s are assisting in the digitization of books, newspapers and radio shows. The service is free and with little effort can be added to your website.

I have been working on a .NET developer community site that requires registration. The site makes use of AJAX and it was decided to that the registration and sign in process would be implement using AJAX. In addition, in order to prevent malicious attacks, reCAPTCHA was added to the registration dialog. The registration dialog is shown below.

registration-reCAPTCHA

The dialog has the typical input fields required for registration but also has the reCAPTCHA to make sure that a human is performing the registration.

This post describes how to add client side reCAPTCHA functionality to your ASP.NET site.

The steps required to add client side reCAPTCHA functionality are:

  1. Register at the reCAPTCHA site. You will receive a public and private API key. The keys are used for encryption. Make sure the private key is hidden away.
  2. Download the ASP.NET server side reCAPTCHA assembly.  
  3. Download the reCAPTCHA client side Javascript. Alternatively, you can just include the Javascript directly for the reCAPTCHA site.
  4. Create an ASP.NET site.
  5. Add Javascript code to create the reCAPTCHA widget.
  6. Add a AJAX enabled web service that accepts the challenge and response data from the reCAPTCHA control.

Steps 1 through 3 are well documented at the reCAPTCHA site and I leave it to the reader to perform these steps. I will also assume that the reader can create a default ASP.NET application.

Adding Javascript to create a reCAPTCHA Widget

Adding client side reCAPTCHA widget to the page is fairly simple. Listing 1 contains the code to display the reCAPTCHA control.

    1 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="recaptcha_client_side._Default" %>

    2 

    3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    4 

    5 <html xmlns="http://www.w3.org/1999/xhtml" >

    6 <head runat="server">

    7     <title></title>

    8 

    9     <script type="text/javascript" src="jquery-1.3.2.js"></script>

   10     <script type="text/javascript" src="http://api.recaptcha.net/js/recaptcha_ajax.js"></script>

   11 

   12     <script type="text/javascript">

   13       $(function() {

   14         Recaptcha.create("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",

   15           'recaptcha',

   16           {

   17             theme: "red"

   18           }

   19         );

   20       });

   21   </script>

   22 

   23 </head>

   24 <body>

   25     <form id="form1" runat="server">

   26 

   27       <div id="recaptcha"></div>

   28       <input id="getperson" type="button" value="Get Person" />     

   29       <div id="greeting"></div>

   30 

   31     </form>

   32 </body>

   33 </html>

Listing 1: Adding client side reCAPTCHA control

First, as shown on line 10, we need to add the reCAPTCHA Javascript file. I have also added the jQuery Javascript library. Next we add a HTML tag that will host the reCAPTCHA widget. I have chosen a div tag and have given it an id of recaptcha (line 27). Finally, using the reCAPTCHA client side function Recaptcha.create, we create the reCAPTCHA widget (lines 12 to 21). Note that the first parameter, shown in the listing as x’s needs to contain the public key. The second parameter is the id of the tag where the reCAPTCHA widget will be rendered. I have also chosen to use the red theme. This Recaptcha.create API has additional parameters. Refer to the reCAPTCHA client library documentation.

Running the application should render the following in the browser.

recaptcha-simple 

 

Add the AJAX-enabled WCF Service

The next step is to create a server side service that will accept the reCAPTCHA challenge response, as entered by the user. Right-click the asp.net project and select Add->New Item.. menu option. This will display the Add New Item dialog from which you can select the AJAX-enabled WCF Service.

add AJAX-enabled WCF service

The name of the service is ServiceWithRecaptcha.svc. After clicking the Add button, the ServiceWithRecaptcha.svc file(s) will be added the asp.net project. Select the code behind for the ServiceWithRecaptcha.svc. The code editor should display the default  implementation for an AJAX-enabled WCF service. Modify the service as per Listing 2.

    1 using System.Runtime.Serialization;

    2 using System.ServiceModel;

    3 using System.ServiceModel.Activation;

    4 using System.ServiceModel.Web;

    5 using System.Web;

    6 

    7 namespace recaptcha_client_side

    8 {

    9     [ServiceContract(Namespace = "")]

   10     [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]

   11     public class ServiceWithRecaptcha

   12     {

   13         [OperationContract]

   14         [WebGet]

   15         public Person GetPerson(string challenge, string response)

   16         {

   17 

   18             Recaptcha.RecaptchaValidator rv = new Recaptcha.RecaptchaValidator

   19             {

   20                 PrivateKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",

   21                 RemoteIP = HttpContext.Current.Request.UserHostAddress,

   22                 Challenge = challenge,

   23                 Response = response

   24             };

   25 

   26             Recaptcha.RecaptchaResponse rr = rv.Validate();

   27             Person p = null;

   28             if (rr.IsValid)

   29             {

   30                 p = new Person { first = "John", last = "Smith"};

   31             }

   32 

   33             return p;

   34         }

   35 

   36     }

   37 

   38     [DataContract]

   39     public class Person

   40     {

   41         [DataMember]

   42         public string first { get; set; }

   43         [DataMember]

   44         public string last { get; set; }

   45     }

   46 }

Listing 2: The AJAX-enabled WCF service. 

The code uses the RecaptchaValidator object which requires a reference to the serve side reCAPTCHA assembly.

In Listing 2, we create a simple function that returns a Person object. The Person class is defined in the code listing and contains only two properties first and last. The class is decorated with the DataContractAttribute indicating that the class is serializable. Both properties are decorated with the DataMemberAttribute meaning that they will be included in the serialization of the object. Remember, unlike web services where properties  are by default included when serialized, in WCF you must opt in.

The actual service class, ServiceWithRecaptcha, is decorated with the ServiceContractAttribute and it’s only function GetPerson is decorated with OperationContractAttribute and WebGetAttribute. This means that the GetPerson function is callable through a HTTP GET method. The GetPerson function accepts two parameters the reCAPTCHA challenge and response from the client side reCAPTCHA API. Prior to returning a person object we call the RecaptchaValidator passing it the private key, shown in x’s, the IP and the challenge and response obtained from the client side (more on this in a bit). The Validate method is then called and if the response, as entered by the user is the same as the challenge then the validator returns true otherwise it returns false. If the validation failed then a null object is returned, otherwise, a Person object is return in JSON serialized format.

Let’s return to the client side code and update it so the the WCF service is called. Listing 3 contains the necessary changes to call the ServiceWithRecaptcha service.

    1 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="recaptcha_client_side._Default" %>

    2 

    3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    4 

    5 <html xmlns="http://www.w3.org/1999/xhtml" >

    6 <head runat="server">

    7     <title></title>

    8 

    9     <script type="text/javascript" src="jquery-1.3.2.js"></script>

   10     <script type="text/javascript" src="http://api.recaptcha.net/js/recaptcha_ajax.js"></script>

   11 

   12     <script type="text/javascript">

   13       $(function() {

   14 

   15         Recaptcha.create("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",

   16           'recaptcha',

   17           {

   18             theme: "red"

   19           }

   20         );

   21 

   22         $('#getperson').click(function() {

   23           ServiceWithRecaptcha.GetPerson(

   24             Recaptcha.get_challenge(),

   25             Recaptcha.get_response(),

   26             function(result) {

   27               if (result != null) {

   28                 $('#greeting').text('Hello there ' + result.first + ' ' + result.last);

   29               }

   30               else {

   31                 $('#greeting').text('The reCAPTCHA text you entered is wrong.');

   32               }

   33             }

   34           );

   35         });

   36 

   37       });

   38   </script>

   39 

   40 </head>

   41 <body>

   42     <form id="form1" runat="server">

   43 

   44       <asp:ScriptManager runat="server">

   45         <Services>

   46           <asp:ServiceReference Path="~/ServiceWithRecaptcha.svc" />

   47         </Services>

   48       </asp:ScriptManager>

   49 

   50       <div id="recaptcha"></div>

   51       <input id="getperson" type="button" value="Get Person" />     

   52       <div id="greeting"></div>

   53 

   54     </form>

   55 </body>

   56 </html>

Listing 3: Client side modification to invoke the AJAX-enabled WCF service.

Two major changes were made to the aspx page.

The first is the inclusion of the ScriptManager, lines 44 to 48. A reference to the the ServiceWithRecaptcha service is included within the ScriptManager tag. This adds the Javascript proxy code that simplifies the calling of the service. To view the Javascript, while in Visual Studio just select the service file and select the View in Browser menu option and then add /js to the URL. This will display the auto-generated Javascript that can be used to call the service.

The second change required is the Javascript to make the call to the service. This code is shown in lines  22 to 38. I have chosen to use jQuery to attach the click event handler to the the input button. The call to the service is done through the proxy generated code, and in our case is the function, ServiceWithRecaptcha.GetPerson. The two parameters, challenge and response, are obtained by calling the Recaptcha APIs  get_challenge and get_response, respectively. The challenge is encrypted via the public key and can only be decrypt by the private key and hence the call to the service.

Try running the code and entering a valid response to the reCAPTCHA widget. The figure below shows the rendered result. Notice that the text Hello there John Smith is displayed, whereas, if an incorrect response was entered the string The reCAPTCHA text you entered is wrong would be displayed.

recaptcha correct response

Currently rated 2.5 by 2 people

  • Currently 2.5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: ASP.NET
Posted by CynotWhyNot on Monday, June 22, 2009 2:00 PM
Permalink | Comments (73) | Post RSSRSS comment feed