Creating a CAPTCHA system

We have been discussing the ability to return images directly from an action quite a bit. It wouldn't seem right if we had all these discussions and didn't quickly demonstrate how to implement a CAPTCHA system. CAPTCHA is defined as Completely Automated Public Turing test to tell Computers and Humans Apart. It is basically a simple challenge and response system to ensure that your system is not interacting with someone else's system when you are expected to be interacting with a human.

Getting ready

We are going to work off of the knowledge that we covered in the previous examples. No external requirements—just more code!

How to do it...

  1. The first most important part to building anything CAPTCHA-related is to have something that generates an image with something easy for a human to parse but difficult for a computer to parse. You can find all sorts of code on the net to do this job. Just Google "C# CAPTCHA" and you will get lists of this sort of tutorial. I also included a class in the Models folder of this project that has the code I usually use. It generates an image like so:
    How to do it...
  2. With a working CAPTCHA class in hand we simply need to wire it up. The first thing for us to do is create a new class in the Models folder called CaptchaResult. This class will inherit from ActionResult like our other recipes.

    CaptchaResult.cs:

    public override void ExecuteResult(ControllerContext context)
    {
    }
    
  3. We are going to need to specify to our CAPTCHA system the text that we want to use to verify the presence of a human. For that reason we need to have a way to pass in the text when we call on the services of our CAPTCHA generator. To do this, we need to add a CaptchaResult constructor like so:

    CaptchaResult.cs:

    public string _captchaText;
    public CaptchaResult(string captchaText)
    {
    _captchaText = captchaText;
    }
    
  4. Now we are ready to create the ExecuteResult method to fulfill our contract with the inherited ActionResult. This is a two-part process. First we need to create an instance of our Captcha class and define a few properties. Then we can save the generated image into the response stream to the browser.

    CaptchaResult.cs:

    public override void ExecuteResult(ControllerContext context)
    {
    Captcha c = new Captcha();
    c.Text = _captchaText;
    c.Width = 200;
    c.Height = 50;
    c.FamilyName = "Century Schoobook";
    HttpContextBase cb = context.HttpContext;
    cb.Response.Clear();
    cb.Response.ContentType = "image/jpeg";
    c.Image.Save(cb.Response.OutputStream, ImageFormat.Jpeg);
    c.Dispose();
    }
    
  5. Now we can turn our attention to getting our home controller ready to spit out a CAPTCHA image. To do this, open the HomeController and add a new CaptchaResult action called GetCaptcha.

    HomeController.cs:

    public CaptchaResult GetCaptcha()
    {
    }
    
  6. Then we need to make a call to our Captcha class to generate the challenge text. We can do this (in this case) with the handy-dandy GenerateRandomCode method that will give us a random number. You can tweak it to do as you like. Then we will stuff that code into a session variable for comparison later.

    HomeController.cs:

    public CaptchaResult GetCaptcha()
    {
    string captchaText = Captcha.GenerateRandomCode();
    HttpContext.Session.Add("captcha", captchaText);
    return new CaptchaResult(captchaText);
    }
    
  7. Now that we have our CaptchaResult wired up as an action, we can call directly and wire up our view. Open the "Index" view for the HomeController. We first need to add a form to our view. Then we will add an image that loads the GetCaptcha method. We will also display a message prompting the user to enter what they see in the image. And we will provide them with a box to enter the text and a button to post their entry.

    Index.aspx:

    <% using (Html.BeginForm("index", "home")) { %>
    <p><img src="/home/getcaptcha" /></p>
    <p>Please enter the number above:</p>
    <p><%=Html.TextBox("captcha")%></p>
    <p><input type="submit" value="Submit" /></p>
    <% } %>
    
  8. This is far enough for you to preview your view. However, we don't have any code yet to handle the comparison aspect of our challenge. To create this, go back to the HomeController. Add a new Index action that expects a String named captcha. Then specify the [HttpPost] attribute to signify that this action will handle only form posts, not gets. Then we can do some simple comparison of what was entered versus what was displayed.

    HomeController.cs:

    [HttpPost]
    public ActionResult Index(string captcha)
    {
    if (captcha == HttpContext.Session["captcha"].ToString())
    ViewData["Message"] = "CAPTCHA challenge was successful!";
    else
    ViewData["Message"] = "CAPTCHA challenge failed - please try again!";
    return View();
    }
    
  9. With all of this complete, you can hit F5 and see the recipe in action. You can enter the number that is displayed to test that it works. And you can enter something totally different from what you see to verify that the challenge system works the other way too.
    How to do it...

How it works...

This recipe is a slight tweak on the previous ones. While we are still generating an image for display in the browser, this time we are generating some form of a text-based challenge for our user, which we store in the user's session. They are responsible for telling us what they see. We then compare what they say with the stored number that they see (which we generated initially).

While this is not an overly fancy code, having a CAPTCHA of this fashion is pretty flexible. You could put a CAPTCHA around your registration pages, on your commenting pages, wherever you need it. Anywhere that you would like to discourage spam is probably a good place for a CAPTCHA deterrent.

There's more...

The CAPTCHA code that I provided with this example is pretty old (I have used it for several years). It has quite a bit of flexibility options in it, in that you can easily adjust the background color, the background image, the color of the font, the color of the foreground and background specs, the font family, and so on. Feel free to poke about and tweak this to suit your needs.

Hatches and colors

You might not like the colors or hatch styles that I chose. No worries, there are quite a few options for you on this front. Take a look at this site to get started: http://www.drewnoakes.com/snippets/GdiColorChart/.

What is CAPTCHA?

You might also be interested in taking a look at Wikipedia for a broader explanation of what CAPTCHA is and the work surrounding that topic. It is quite interesting. http://en.wikipedia.org/wiki/CAPTCHA.

Other styles of CAPTCHA

CAPTCHA is a big area of study. CAPTCHA doesn't only come in the form of an image with distorted letters and numbers. There are projects such as reCAPTCHA (http://recaptcha.net/), SQUIGL-PIX, ESP-PIX, and a fancy drag-and-drop jQuery plug-in.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset