Click here to Skip to main content
15,868,016 members
Articles / Web Development / ASP.NET

Building ASP.NET Bot protection (CAPTCHA-like)

Rate me:
Please Sign up or sign in to vote.
4.57/5 (24 votes)
15 Oct 2007CPOL3 min read 102.5K   2.8K   67   22
Shows how to build captcha like protection against spam and other bots.

Screenshot - captcha.jpg

Introduction

One day, I decided to build my own CAPTCHA for my project. Why? First of all, I needed a quite strong bot protection. Second reason - I wanted to make my contribution for the community. And that's why I decided to make this project completely free for use.

Why am I thinking that the result of my work is a really strong protection? First of all, it's new - so there are no ready OCRs for this one. Also, you can change it by yourself - and receive a completely different CAPTCHA. I'm calling my CAPTCHA "ADSS AntiBot". I've a friend, who breaks security using OCRs. And he said to me - not very bad.

You can make your own protection based on this (link to us greatly appreciated, ADSS).

Background

Everybody knows that the world wide web is filled up with spam bots. And webmasters (usually using developers) fight against this problem. Every webmaster dreams about real visitors, not about thousands of bots using some service and even reselling it on another website. The things known as CAPTCHA ("Completely Automated Public Turing test to tell Computers and Humans Apart") were made to fight against bots. I'm using the term AntiBot for my application.

Using the Code

How to use the downloaded source? Very easy. Just put some image on your ASP.NET page with ImageURL set to captcha.ashx. This handler generates a new image each time it is accessed, and stores the right value into the session.

C#
string number_server_side = (string)Session[ADSSAntiBot.SESSION_CAPTCHA];
if (number_server_side == TextBox_number.Text)
{
    // The code entered is valid
}
else
{
    // The code entered invalid
}

This way, you can use the created HTTP handler.

Another thing I want to note is the image size. You can easily set it using the ADSSAntiBot public constructor inside the ProcessRequest function of the handler.

C#
public void ProcessRequest (HttpContext context) {
    context.Response.ContentType = "image/jpeg";
    ADSSAntiBot captcha = new ADSSAntiBot(300,80); // Set size using constructor
    string str = captcha.DrawNumbers(5);
    if (context.Session[ ADSSAntiBot.SESSION_CAPTCHA] == null)
        context.Session.Add(ADSSAntiBot.SESSION_CAPTCHA, str);
    else
    {
        context.Session[ ADSSAntiBot.SESSION_CAPTCHA] = str;
    }
    Bitmap bmp = captcha.Result;
    bmp.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
}

The picture below shows the result of this code. Sometimes you want a large image, sometimes a small one.

Screenshot - large_captcha.jpg

Points of Interest

So, how we are creating this "hard to OCR" image? And how can we improve it?

We use GraphicsPath to wrap the image. Basically, the transformation is a sin wave, regular random noise, and some rotation. What is the goal? To create text that can be read by humans, not by a bot. How are we doing this? We "shake" the subpaths of our text.

What is the goal of the transform? First of all, we need to change it to make letter separation hard. For this, we add a line through all the numbers displayed. Second, we need to remember that our numbers should be hard to identify for the OCR using a neural network. By moving path points randomly and by using a sin wave, we are making the line very thick in some places. On the sample image, you can see this effect on "9" and "6".

The following function is the heart of our transformation:

C#
public GraphicsPath RandomWarp(GraphicsPath path)
{
    // Add line //
    int PsCount = 10;
    PointF[] curvePs = new PointF[PsCount * 2];
    for (int u = 0; u < PsCount; u++)
    {
        curvePs[u].X = u * (Width / PsCount);
        curvePs[u].Y = Height / 2;
    }
    for (int u = PsCount; u < (PsCount * 2); u++)
    {
        curvePs[u].X = (u - PsCount) * (Width / PsCount);
        curvePs[u].Y = Height / 2 + 2;
    }
    path.AddLines(curvePs);
   
    double eps = Height * 0.05;
    double amp = rnd.NextDouble() * (double)(Height / 3);
    double size = rnd.NextDouble() * (double)(Width / 4) + Width / 8;
    double offset = (double)(Height / 3);

    PointF[] pn = new PointF[path.PointCount];
    byte[] pt = new byte[path.PointCount];

    GraphicsPath np2 = new GraphicsPath();

    GraphicsPathIterator iter = new GraphicsPathIterator(path);
    for (int i = 0; i < iter.SubpathCount; i++)
    {
        GraphicsPath sp = new GraphicsPath();
        bool closed;
        iter.NextSubpath(sp, out closed);

        Matrix m = new Matrix();
        m.RotateAt(Convert.ToSingle(rnd.NextDouble() * 30 - 15), 
                   sp.PathPoints[0]);
        m.Translate(-1 * i, 0);
        sp.Transform(m);
        np2.AddPath(sp, true);
    }
    for (int i = 0; i < np2.PointCount; i++)
    {
        pn[i] = Wave(np2.PathPoints[i], amp, size);
        pt[i] = np2.PathTypes[i];
    }
    GraphicsPath newpath = new GraphicsPath(pn, pt);
    return newpath;
}

We are not using a lot of fonts like others do, and not using colors. The color model only helps OCRing many captchas; font is not an obstacle too. But here, we are making a "random" font using this wrap. I just wanted to show that the .NET Framework makes it possible to protect a site from bots much better then other frameworks. Also, I'm interested in your suggestions about non-captcha bot protections. I'm going to continue my research in this direction.

History

The code described in this article is complete freeware. You can try it online.

Also, you can download the latest version from the ADSS website. Feel free to create your CAPTCHAs based on this one to fight against spam.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Ukraine Ukraine
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
ravizia21-Oct-11 4:21
ravizia21-Oct-11 4:21 
GeneralMy vote of 5 Pin
Ram Kumar(Webunitech)10-Oct-11 8:39
Ram Kumar(Webunitech)10-Oct-11 8:39 
Questionrefresh button? Pin
Member 818310123-Aug-11 13:09
Member 818310123-Aug-11 13:09 
GeneralVery Very Nice Pin
blagoja30-Jul-09 21:44
blagoja30-Jul-09 21:44 
GeneralI used in my project and convert it into vb Thanks for your code Pin
jefferycxl20-Jan-09 16:56
jefferycxl20-Jan-09 16:56 
GeneralHelp please! Pin
Patrik Svitek11-Mar-08 11:26
Patrik Svitek11-Mar-08 11:26 
GeneralCaptcha not working with UpdatePanel Pin
DynamicPages10-Feb-08 23:15
DynamicPages10-Feb-08 23:15 
GeneralRe: Captcha not working with UpdatePanel Pin
macload14-Dec-09 9:24
macload14-Dec-09 9:24 
QuestionBrowser incompatibility? Pin
nemopeti15-Oct-07 9:02
nemopeti15-Oct-07 9:02 
AnswerRe: Browser incompatibility? Pin
Dmitry Salko15-Oct-07 9:09
Dmitry Salko15-Oct-07 9:09 
General4 out of 5 Bad Pin
crb90009-Oct-07 4:49
crb90009-Oct-07 4:49 
GeneralRe: 4 out of 5 Bad Pin
Dmitry Salko9-Oct-07 5:23
Dmitry Salko9-Oct-07 5:23 
GeneralNice code, but nothing new Pin
Sire4049-Oct-07 4:44
Sire4049-Oct-07 4:44 
GeneralRe: Nice code, but nothing new Pin
Dmitry Salko9-Oct-07 5:01
Dmitry Salko9-Oct-07 5:01 
GeneralRe: Nice code, but nothing new Pin
Sire4049-Oct-07 5:09
Sire4049-Oct-07 5:09 
It can't, and I haven't found any other solution that work well either.

But successfully registering to a free email service isn't the goal, sending spam is - and it will stop that very efficiently.


--------------------
No one is perfect.
Welll, there was this guy... but we killed him.

QuestionWhat about vision impaired surfers? Pin
Bcouch9-Oct-07 1:51
Bcouch9-Oct-07 1:51 
AnswerRe: What about vision impaired surfers? Pin
Dmitry Salko9-Oct-07 3:36
Dmitry Salko9-Oct-07 3:36 
GeneralVery Nice Pin
merlin9818-Oct-07 4:31
professionalmerlin9818-Oct-07 4:31 
GeneralRe: Very Nice Pin
Dmitry Salko8-Oct-07 4:37
Dmitry Salko8-Oct-07 4:37 
GeneralNice Pin
Ben Daniel7-Oct-07 12:51
Ben Daniel7-Oct-07 12:51 
GeneralRe: Nice Pin
Dmitry Salko7-Oct-07 22:14
Dmitry Salko7-Oct-07 22:14 
GeneralRe: Nice Pin
Ben Daniel15-Oct-07 20:42
Ben Daniel15-Oct-07 20:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.