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.
We are going to work off of the knowledge that we covered in the previous examples. No external requirements—just more code!
Models
folder of this project that has the code I usually use. It generates an image like so: Models
folder called CaptchaResult
. This class will inherit from ActionResult
like our other recipes.CaptchaResult.cs:
public override void ExecuteResult(ControllerContext context) { }
CaptchaResult
constructor like so:CaptchaResult.cs:
public string _captchaText; public CaptchaResult(string captchaText) { _captchaText = captchaText; }
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(); }
CaptchaResult
action called GetCaptcha
.HomeController.cs:
public CaptchaResult GetCaptcha() { }
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); }
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> <% } %>
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(); }
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.
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.
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/.
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.
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.