How to use Captcha using ASP.NET C# and jQuery


Hi Guys,

Recently I was working on a project where I had to use the captcha technology to prevent misuse of a Form. My code was written in C# (2.0) so I was looking for a easy solution in C# only. I was also using jQuery plugin and thought if there is such a tool it can be very useful.

So, I ask my god Google to find me such a tool. There was lot of great example but somehow then didn’t caught my attention. Suddenly I found a very useful example in CodeProject site (http://www.codeproject.com/Articles/5947/CAPTCHA-Image)

I started to debug the code after downloading it. There were few problems (may be I was not using the proper environment). Also, to generate a new captcha one had to submit the page which I don’t really want. But this post gave me the required motivation to modify the script in such a way that it will suit my need. Finally, I got it to work.

Now, I don’t want someone in the same problem work on the same project from scratch. This is why I thought this tool can be a useful one to post in the site.

Now, I wanted to make sure that the image can be refreshed. so, I have used jQuery and add an onclick event in the image. If the captcha is successful it will display a dialogue like following:

Else, it will display an error. Also, in this case the I had to make sure that the Captcha is changed.

Here are some technical details. Full project also you can download.

First of all, add a reference to jQuery file. You can use a CDN as well (like I did)

<script src=”http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.js&#8221; type=”text/javascript”></script>

Now, build the HTML.

<body>
<h2>
MyCaptchaImage Test</h2>
<p>
A demonstration using the <code>CaptchaImage</code> object to prevent automated
form submission.</p>
<form id=”frmDef” method=”post” runat=”server”>
<img id=”captcha” src=”JpegImage.aspx?rnd=<%=_rand.Next(10).ToString() %>” alt=”Captcha Image” /><br />
<span>Click Image to Geneate a new captcha</span>
<p>
<strong>Enter the code shown above:</strong><br />
<asp:TextBox ID=”CodeNumberTextBox” runat=”server”></asp:TextBox>
<asp:Button ID=”SubmitButton” runat=”server” Text=”Submit”></asp:Button><br />
</p>
<p>
<em class=”notice”>(Note: If you cannot read the numbers in the above<br />
image, Click the Image to generate a new one.)</em>
</p>
<p>
<asp:Label ID=”MessageLabel” runat=”server”></asp:Label></p>
</form>
</body>

At this point you need to create the refresh method by jQuery:

<script type=”text/javascript”>

$(document).ready(function() {
// refresh captcha
$(‘img#captcha’).click(function() {
change_captcha();
});

function change_captcha()
{
document.getElementById(‘captcha’).src=”JpegImage.aspx?rnd=” + Math.random();
}
});
</script>

Here is the Default.aspx.cs file

public partial class _Default : System.Web.UI.Page
{
public Random _rand = new Random();

private void Page_Load(object sender, System.EventArgs e)
{
if (this.IsPostBack)
{
string _capStr = this.Session[“CaptchaImageText”].ToString();
// On a postback, check the user input.
if (this.CodeNumberTextBox.Text == _capStr)
{
// Display an informational message.
this.MessageLabel.CssClass = “info”;
this.MessageLabel.Text = “Correct!”;
this.CodeNumberTextBox.Text = “”;
}
else
{
// Display an error message.
this.MessageLabel.CssClass = “error”;
this.MessageLabel.Text = “ERROR: Incorrect, try again.”;

// Clear the input
this.CodeNumberTextBox.Text = “”;
}
}
}
}

As you can see, I have used a Random number generation method while calling the “JpegImage.aspx” as well. This will ensure that every time you reload the page or submit the page a new captcha is generated.

JpegImage.aspx.cs file is as follows. Whenever we’ll call it it will generate a new Captcha.

 

public partial class JpegImage : System.Web.UI.Page
{
private void Page_Load(object sender, System.EventArgs e)
{
if (!IsPostBack)
{
this.Session[“CaptchaImageText”] = CaptchaImage.GenerateRandomCode();

// Create a CAPTCHA image using the text stored in the Session object.
CaptchaImage ci = new CaptchaImage(this.Session[“CaptchaImageText”].ToString(), 200, 50, “Century Schoolbook”);

// Change the response headers to output a JPEG image.
this.Response.Clear();
this.Response.ContentType = “image/jpeg”;

// Write the image to the response stream in JPEG format.
ci.Image.Save(this.Response.OutputStream, ImageFormat.Jpeg);

// Dispose of the CAPTCHA image object.
ci.Dispose();
}
}
}

 

The Captcha image class file is not changed a lot. Only I had to move the Random code generation script to this file so that I don’t have to create a new class. You can move it to a new class file if you like.

 

// ====================================================================
// Creates the bitmap image.
// ====================================================================
private void GenerateImage()
{
// Create a new 32-bit bitmap image.
Bitmap bitmap = new Bitmap(this.width, this.height, PixelFormat.Format32bppArgb);

// Create a graphics object for drawing.
Graphics g = Graphics.FromImage(bitmap);
g.SmoothingMode = SmoothingMode.AntiAlias;
Rectangle rect = new Rectangle(0, 0, this.width, this.height);

// Fill in the background.
HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White);
g.FillRectangle(hatchBrush, rect);

// Set up the text font.
SizeF size;
float fontSize = rect.Height + 1;
Font font;
// Adjust the font size until the text fits within the image.
do
{
fontSize–;
font = new Font(this.familyName, fontSize, FontStyle.Bold);
size = g.MeasureString(this.text, font);
} while (size.Width > rect.Width);

// Set up the text format.
StringFormat format = new StringFormat();
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;

// Create a path using the text and warp it randomly.
GraphicsPath path = new GraphicsPath();
path.AddString(this.text, font.FontFamily, (int)font.Style, font.Size, rect, format);
float v = 4F;
PointF[] points =
{
new PointF(this.random.Next(rect.Width) / v, this.random.Next(rect.Height) / v),
new PointF(rect.Width – this.random.Next(rect.Width) / v, this.random.Next(rect.Height) / v),
new PointF(this.random.Next(rect.Width) / v, rect.Height – this.random.Next(rect.Height) / v),
new PointF(rect.Width – this.random.Next(rect.Width) / v, rect.Height – this.random.Next(rect.Height) / v)
};
Matrix matrix = new Matrix();
matrix.Translate(0F, 0F);
path.Warp(points, rect, matrix, WarpMode.Perspective, 0F);

// Draw the text.
hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.LightGray, Color.DarkGray);
g.FillPath(hatchBrush, path);

// Add some random noise.
int m = Math.Max(rect.Width, rect.Height);
for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++)
{
int x = this.random.Next(rect.Width);
int y = this.random.Next(rect.Height);
int w = this.random.Next(m / 50);
int h = this.random.Next(m / 50);
g.FillEllipse(hatchBrush, x, y, w, h);
}

// Clean up.
font.Dispose();
hatchBrush.Dispose();
g.Dispose();

// Set the image.
this.image = bitmap;
}

You can find the complete project file here. Please let me know if you got any problems.