Have you ever wondered how to create a Captcha for your web forms, well its really simple and it wont take more than 100+ lines of code. This sample captcha that I will demostrate will have random Font Type, Font Style, Font Color, Font Rotation, Background Style and Background Colour. Here are some samples of what this can generate:
Now without too much explanation, here it goes.
Step 1 : In your web project add a Generic Handler thats the file with the.ahsx extension, Ill just use this for this demo for simplicity and also it will compile on demand like a normal aspx file. Its up to you if you want to create a dll which is better so you can reuse it in any projects you want. To do that right click on the project on your Solution Explorer.
Then choose your file type, in this sample its a Generic Handler
Step 2 : Once added you can start coding, here are the sample codes which you can freely copy.
<%@ WebHandler Language="C#" %> using System; using System.Web; using System.Drawing; using System.IO; using System.Web.SessionState; using System.Drawing.Imaging; using System.Drawing.Text; using System.Drawing.Drawing2D; public class Captcha : IHttpHandler, IReadOnlySessionState { public void ProcessRequest(HttpContext context) { int iHeight = 80; int iWidth = 190; Random oRandom = new Random(); int[] aBackgroundNoiseColor = new int[] { 150, 150, 150 }; int[] aTextColor = new int[] { 0, 0, 0 }; int[] aFontEmSizes = new int[] { 15, 20, 25, 30, 35 }; string[] aFontNames = new string[] { "Comic Sans MS", "Arial", "Times New Roman", "Georgia", "Verdana", "Geneva" }; FontStyle[] aFontStyles = new FontStyle[] { FontStyle.Bold, FontStyle.Italic, FontStyle.Regular, FontStyle.Strikeout, FontStyle.Underline }; HatchStyle[] aHatchStyles = new HatchStyle[] { HatchStyle.BackwardDiagonal, HatchStyle.Cross, HatchStyle.DashedDownwardDiagonal, HatchStyle.DashedHorizontal, HatchStyle.DashedUpwardDiagonal, HatchStyle.DashedVertical, HatchStyle.DiagonalBrick, HatchStyle.DiagonalCross, HatchStyle.Divot, HatchStyle.DottedDiamond, HatchStyle.DottedGrid, HatchStyle.ForwardDiagonal, HatchStyle.Horizontal, HatchStyle.HorizontalBrick, HatchStyle.LargeCheckerBoard, HatchStyle.LargeConfetti, HatchStyle.LargeGrid, HatchStyle.LightDownwardDiagonal, HatchStyle.LightHorizontal, HatchStyle.LightUpwardDiagonal, HatchStyle.LightVertical, HatchStyle.Max, HatchStyle.Min, HatchStyle.NarrowHorizontal, HatchStyle.NarrowVertical, HatchStyle.OutlinedDiamond, HatchStyle.Plaid, HatchStyle.Shingle, HatchStyle.SmallCheckerBoard, HatchStyle.SmallConfetti, HatchStyle.SmallGrid, HatchStyle.SolidDiamond, HatchStyle.Sphere, HatchStyle.Trellis, HatchStyle.Vertical, HatchStyle.Wave, HatchStyle.Weave, HatchStyle.WideDownwardDiagonal, HatchStyle.WideUpwardDiagonal, HatchStyle.ZigZag }; //Get Captcha in Session string sCaptchaText = context.Session["Captcha"].ToString(); //Creates an output Bitmap Bitmap oOutputBitmap = new Bitmap(iWidth, iHeight, PixelFormat.Format24bppRgb); Graphics oGraphics = Graphics.FromImage(oOutputBitmap); oGraphics.TextRenderingHint = TextRenderingHint.AntiAlias; //Create a Drawing area RectangleF oRectangleF = new RectangleF(0, 0, iWidth, iHeight); Brush oBrush = default(Brush); //Draw background (Lighter colors RGB 100 to 255) oBrush = new HatchBrush(aHatchStyles[oRandom.Next(aHatchStyles.Length - 1)], Color.FromArgb((oRandom.Next(100, 255)), (oRandom.Next(100, 255)), (oRandom.Next(100, 255))), Color.White); oGraphics.FillRectangle(oBrush, oRectangleF); System.Drawing.Drawing2D.Matrix oMatrix = new System.Drawing.Drawing2D.Matrix(); int i = 0; for (i = 0; i <= sCaptchaText.Length - 1; i++) { oMatrix.Reset(); int iChars = sCaptchaText.Length; int x = iWidth / (iChars + 1) * i; int y = iHeight / 2; //Rotate text Random oMatrix.RotateAt(oRandom.Next(-40, 40), new PointF(x, y)); oGraphics.Transform = oMatrix; //Draw the letters with Randon Font Type, Size and Color oGraphics.DrawString ( //Text sCaptchaText.Substring(i, 1), //Random Font Name and Style new Font(aFontNames[oRandom.Next(aFontNames.Length - 1)], aFontEmSizes[oRandom.Next(aFontEmSizes.Length - 1)], aFontStyles[oRandom.Next(aFontStyles.Length - 1)]), //Random Color (Darker colors RGB 0 to 100) new SolidBrush(Color.FromArgb(oRandom.Next(0, 100), oRandom.Next(0, 100), oRandom.Next(0, 100))), x, oRandom.Next(10, 40) ); oGraphics.ResetTransform(); } MemoryStream oMemoryStream = new MemoryStream(); oOutputBitmap.Save(oMemoryStream, System.Drawing.Imaging.ImageFormat.Png); byte[] oBytes = oMemoryStream.GetBuffer(); oOutputBitmap.Dispose(); oMemoryStream.Close(); context.Response.BinaryWrite(oBytes); context.Response.End(); } public bool IsReusable { get { return false; } } }
There are some commented explanation along the way so you wont get lost, but you can still ask me if you really need.
Step 3 : Use that Captcha. On your aspx add the following as an image like such
<asp:Image ID="imgCaptcha" ImageUrl="Captcha.ashx" runat="server" />
If you noticed its like your using it as an image, this is because its an image rendered by that handler which you can see on the bottom part of the captcha code
context.Response.BinaryWrite(oBytes);
Step 4 : Assign a text on that captcha on your code behind
private void SetCaptchaText() { Random oRandom = new Random(); int iNumber = oRandom.Next(100000, 999999); Session["Captcha"] = iNumber.ToString(); }
Note : You may notice that I am using only numbers in this regard, this would be easy so users cannot be confused with l and 1, 0 and o, and other similar looking characters.
Note: By setting the session you are also setting the text to render on the captcha and if you look at the captcha codes it is in this section
string sCaptchaText = context.Session["Captcha"].ToString();
Step 5 : Compare that to value to what the users had keyed in to your text box
if (Session["Captcha"].ToString() != txtCaptcha.Text.Trim()) { Response.Redirect("Failed.aspx"); } else { Response.Redirect("Success.aspx"); }
Thats it, Congratulations you have created your own captcha
Its giving me an error at runtime..!!
it says “object referrence not set to an instance of an object” at the following line…
string sCaptchaText = context.Session[“Captcha”].ToString();
It looks like the session was not found, have to tried doing Step 4? If yes can you give me the codes for Setting your session.
Hi
where did we have to call this method ? is it in handler file ?
private void SetCaptchaText()
{
Random oRandom = new Random();
int iNumber = oRandom.Next(100000, 999999);
Session[“Captcha”] = iNumber.ToString();
}
My apologies if it was not clear but you need 3 files.
1. Your handler file which is the one in Step 2
2a. Your page where you put your captcha (The aspx part)
2b. Your page where you put your captcha (The code behind or .cs part) -Thats the place you will put your method in question.
Hope this is clear.
Hi!
compliment for the articles.
But i have a problem. I don’t run your solution on IIS 7 on Windows 2008 R2.
You have a solution?
Tnx!!
pit
What are you using?
why the image wont come out ?
can you send me the codes so I can properly debug what you mean.
captcha image cant be viewed.
as you mentioned, there are 3 files: Captcha.ashx, default.aspx, default.aspx.cs
I guess ı have a problem in default.aspx file:
*Security Code:
Can show me your codes on your default.aspx so I can debug for you.
Thank you for quick reply. But code in default.aspx cant be copied into the related box.
Can you please send an e-mail address?
I have a little problem with the captcha, sometimes it can be hard to see the order in which the characters are in. Is there any possibility to increase the distance between the characters?
Otherwise, it works brilliantly.
Sorry for the slow reply but, The Captcha Text spacing is auto adjusting depending on how long the string is relative to the width of the image, so you can either reduce the characters on the string or widen the image thats the int iWidth = 190 declaration
One more question. I would like to switch from storing capchan in a session to store the Captcha in a hidden-field, what changes do I need to do?
Even if you put it in Hidden Field you still need to assign a value on sCaptchaText, so you still put it in a Seesion Variable or a Global variable that your application can get and set.
Cant change captcha img. I put the “SetCaptchaText()” and “imgCaptcha.ImageUrl = ‘Captcha.ashx'” under Onclick event but still image keeps the same image. But session value changed. So how can I do that?
Thanks for your help
Can you send me the codes so I can properly see whats happening
hi,
am having same problem of session as Priyank…
other wise it works great..
problem solved !!!!
use
public class Capthca : IHttpHandler, System.Web.SessionState.IRequiresSessionState
or
use
System.Web.SessionState.IRequiresSessionState if you want to access session in handler.
Its giving me an error at runtime..!!
it says “object referrence not set to an instance of an object” at the following line…
string sCaptchaText = context.Session[“Captcha”].ToString();
It means your context.Session[“Captcha”] does not have a valie please check how you assign value to your session
i cant see an image when i run ur codes..
Hi!! I do this tutorial, but i have a problem, when I execute I cant see the image pliss help me!! thanks!!!
Thanks.
How do i make the numbers fit inside the image.? Few numbers are not visible fully since I changed the height to 50 and the numbers are getting cut
I figured out why the image doesnt display. I added
context.Response.ContentType = “image/png”;
above this line:
MemoryStream oMemoryStream = new MemoryStream();
Have a good day.
and removed context.Reponse.End(); in the bottom.
Excuse me .. I’m not understand step 3 onward.. where should i put the code (step 3) ?
It just says you use the code Captcha.ashx like how you use a normal image
Where should I put this?
private void SetCaptchaText()
{
Random oRandom = new Random();
int iNumber = oRandom.Next(100000, 999999);
Session[“Captcha”] = iNumber.ToString();
}
On Page load of your website before you display the image