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.
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 (CustomCaptcha
) to 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
- http://www.dotnetfunda.com/codes/show/6552/captcha-implementation-using-aspnet
- http://stackoverflow.com/questions/2070365/how-to-generate-an-image-from-text-on-fly-at-runtime