Have you ever wondered how to create a Captcha for your web forms? Well, it's really simple and it won't take more than 100+ lines of code. This sample captcha that I will demonstrate 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 that's the file with the .ahsx extension. I'll just use this for this demo for simplicity and also it will compile on demand like a normal aspx file. It's 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, it's 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
};
string sCaptchaText = context.Session["Captcha"].ToString();
Bitmap oOutputBitmap = new Bitmap(iWidth, iHeight, PixelFormat.Format24bppRgb);
Graphics oGraphics = Graphics.FromImage(oOutputBitmap);
oGraphics.TextRenderingHint = TextRenderingHint.AntiAlias;
RectangleF oRectangleF = new RectangleF(0, 0, iWidth, iHeight);
Brush oBrush = default(Brush);
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;
oMatrix.RotateAt(oRandom.Next(-40, 40), new PointF(x, y));
oGraphics.Transform = oMatrix;
oGraphics.DrawString
(
sCaptchaText.Substring(i, 1),
new Font(aFontNames[oRandom.Next(aFontNames.Length - 1)],
aFontEmSizes[oRandom.Next(aFontEmSizes.Length-1)],
aFontStyles[oRandom.Next(aFontStyles.Length - 1)]),
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 is some commented explanation along the way so you won't 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, it's like you are using it as an image, this is because it's 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 value to what the users had keyed into your text box:
if (Session["Captcha"].ToString() != txtCaptcha.Text.Trim())
{
Response.Redirect("Failed.aspx");
}
else
{
Response.Redirect("Success.aspx");
}
That's it. Congratulations! You have created your own captcha.