Implementing simple custom captcha in ASP.NET MVC

Sheonarayan
Posted by in ASP.NET MVC category on for Intermediate level | Points: 250 | Views : 25727 red flag
Rating: 5 out of 5  
 2 vote(s)

In this article, we shall learn how to implement simple CAPTCHA (that is used to stop automated robots or scripts to submit malicious data) in ASP.NET MVC.
Recommendation
Read Implementing Google reCAPTCHA in ASP.NET MVC before this article.

What is CAPTCHA?

Spam and promotional posts are becoming unmanageable for the webmasters these days. There are several ways to tackle this issue and CAPTCHA is one of them. CAPTCHA helps in stopping automated robots and scripts to submit malicious data to the server.

CAPTCHA is basically few characters written on an image that a real user reads and writes into the designated text box to validate. It is assumed that an automated robots or script can't read the text on the image. If exact text of the image is written into designated text box then at form submission it is validated (generally at server side) against the CAPTCHA image text. If both are same, the request is considered by a real user otherwise the data is ignored assuming some automated robots or scripts is making malicious request.

In this article, we shall learn a simple CAPTCHA implementation in ASP.NET MVC.

Implementing simple custom captcha in ASP.NET MVC


Let's first create a sample Login view that looks like below.


The code snippet of above View is below. Here, we have two text boxes and img tag that calls the GetCaptchaImage action method of the Home controller to display the captcha image.

<h2>Custom Captcha</h2>
<form method="post" action="/Home/CustomCaptcha">
    @Html.AntiForgeryToken()
    <p>
        Username: <input type="text" name="username" />
    </p>
    <p>
        Password: <input type="password" name="password" />
    </p>
    <div>
        <img src="/Home/GetCaptchaImage" title="Captcha"/>
        <br />
        <input type="text" name="clientCaptcha" placeholder="Write above text exactly" required />
        <p style="font-weight:bold;color:red;">@ViewBag.CaptchaError</p>
    </div>
    <p>
        <input type="submit" name="btn" value="Submit"/>
    </p>
</form>


Returning CAPTCHA image from controller in ASP.NET MVC

This part contains three steps and we shall learn all of them below.

First let's create a function (GetRandomText function) that returns random string, this code has been taken from this post of DotNetFunda.com.

Next, we have an action method that returns view (CustomCaptchato the browser. This method simply saves the random string into the Session to be used by captcha image generator function (GetCaptchaImage) and to validate the request.

Now, let's create a function (GetCaptchaImage function) in the controller that returns the CAPTCHA image. Most part of this code has been taken from Stackoverflow thread that is referenced at the bottom of this article. I have changed this code snippet a bit to fit in our requirement.

In GetCaptchaImage action method whose return type if FileResult as it returns the captcha image file, we retrieved the random string saved into Session and then generated an image that contains this string. Most of the code snippet of this function is self explanatory and well commented. In case you are feeling difficulty in understanding this, feel free to respond this article and I would be happy to explain. 

        /// <summary>
        /// get random string
        /// </summary>
        /// <returns></returns>
        private string GetRandomText()
        {
            StringBuilder randomText = new StringBuilder();
            string alphabets = "012345679ACEFGHKLMNPRSWXZabcdefghijkhlmnopqrstuvwxyz";
            Random r = new Random();
            for (int j = 0; j <= 5; j++)
            {
                randomText.Append(alphabets[r.Next(alphabets.Length)]);
            }
            return randomText.ToString();
        }

        public ActionResult CustomCaptcha()
        {
            Session["CAPTCHA"] = GetRandomText();
            return View();
        }

        public FileResult GetCaptchaImage()
        {
            string text = Session["CAPTCHA"].ToString();
            
            //first, create a dummy bitmap just to get a graphics object
            Image img = new Bitmap(1, 1);
            Graphics drawing = Graphics.FromImage(img);

            Font font = new Font("Arial", 15);
            //measure the string to see how big the image needs to be
            SizeF textSize = drawing.MeasureString(text, font);
            
            //free up the dummy image and old graphics object
            img.Dispose();
            drawing.Dispose();

            //create a new image of the right size
            img = new Bitmap((int)textSize.Width + 40, (int)textSize.Height + 20);
            drawing = Graphics.FromImage(img);

            Color backColor = Color.SeaShell;
            Color textColor = Color.Red;
            //paint the background
            drawing.Clear(backColor);

            //create a brush for the text
            Brush textBrush = new SolidBrush(textColor);

            drawing.DrawString(text, font, textBrush, 20, 10);

            drawing.Save();

            font.Dispose();
            textBrush.Dispose();
            drawing.Dispose();

            MemoryStream ms = new MemoryStream();
            img.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
            img.Dispose();

            return File(ms.ToArray(), "image/png");
        }       

Above code snippets will render the view with the captcha image that is shown in the above picture. Now let's see what happens when a request is submitted using above form.

Validating CAPTCHA image in ASP.NET MVC controller

Now, if a real user submits the form after entering proper data into username and password text and  characters of the CAPTCHA image into the text box then below action method fires.

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult CustomCaptcha(FormCollection form)
        {
            string clientCaptcha = form["clientCaptcha"];
            string serverCaptcha = Session["CAPTCHA"].ToString();

            if (!clientCaptcha.Equals(serverCaptcha))
            {
                ViewBag.ShowCAPTCHA = serverCaptcha;

                ViewBag.CaptchaError = "Sorry, please write exact text as written above.";
                return View();
            }

            // go ahead and validate username and password
            string userName = form["username"];
            string password = form["password"];

            return RedirectToAction("Index");
        }
In above code snippet, first we retrieve the captcha text box value into clientCaptcha variable and then retrieve the Session data that was stored in the CustomCaptcha action method of the first code snippet above.

Both are validated and if both are NOT exatly same, an error message is written in the ViewBag and the view is returned otherwise we go ahead and do the database validations for the login. In this case, I have simply returned to user to the Index action method.



Thats it! You have your own custom captcha implementation ready. Feel free to exactly use this code into your project (even in commerical projects). It is all free !

Conclusion

In this article, we learnt how to generate a random string, generate a CAPTCHA image using that string and renders the image on the view. After that validate the CAPTCHA text with user input and return proper response to the user.

Thanks for reading. Hope this article was easy to understand. Do write your comment or feedback by replying below.

Reference

  1. http://www.dotnetfunda.com/codes/show/6552/captcha-implementation-using-aspnet
  2. http://stackoverflow.com/questions/2070365/how-to-generate-an-image-from-text-on-fly-at-runtime
Page copy protected against web site content infringement by Copyscape

About the Author

Sheonarayan
Full Name: Sheo Narayan
Member Level: HonoraryPlatinum
Member Status: Administrator
Member Since: 7/8/2008 6:32:14 PM
Country: India
Regards, Sheo Narayan http://www.dotnetfunda.com

Ex-Microsoft MVP, Author, Writer, Mentor & architecting applications since year 2001. Connect me on http://www.facebook.com/sheo.narayan | https://twitter.com/sheonarayan | http://www.linkedin.com/in/sheonarayan

Login to vote for this post.

Comments or Responses

Posted by: Bhuvanesh6 on: 7/21/2016 | Points: 25
Is this the same way for implementing the image for captcha which shows some number as door number or bus number captcha in some websites?

Login to post response

Comment using Facebook(Author doesn't get notification)