65.9K
CodeProject 正在变化。 阅读更多。
Home

构建 ASP.NET 机器人防护(类似验证码)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.57/5 (20投票s)

2007年10月7日

CPOL

3分钟阅读

viewsIcon

105766

downloadIcon

2851

展示如何构建类似验证码的防护来抵御垃圾邮件和其他机器人。

Screenshot - captcha.jpg

引言

有一天,我决定为我的项目构建自己的验证码。为什么?首先,我需要一个相当强大的机器人防护。第二个原因 - 我想为社区做贡献。这就是我决定将这个项目完全免费使用的原因。

为什么我认为我的工作成果是一个真正强大的防护?首先,它是新的 - 所以没有现成的 OCR 可以识别它。此外,您可以自己更改它 - 并获得一个完全不同的验证码。我称我的验证码为“ADSS AntiBot”。我有一个朋友,他使用 OCR 破解安全性。他说 - 不错。

您可以基于此创建自己的防护(非常感谢链接到我们,ADSS)。

背景

众所周知,万维网充满了垃圾邮件机器人。网站管理员(通常使用开发人员)与这个问题作斗争。每个网站管理员都梦想着真正的访问者,而不是数千个使用某些服务甚至在另一个网站上转售的机器人。被称为验证码(“完全自动化公共图灵测试以区分计算机和人类”)的东西是为了对抗机器人而制作的。我将 AntiBot 术语用于我的应用程序。

Using the Code

如何使用下载的源代码?非常简单。只需在您的 ASP.NET 页面上放置一些图像,并将ImageURL设置为captcha.ashx。此处理程序每次被访问时都会生成一个新图像,并将正确的值存储到会话中。

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
}

这样,您就可以使用创建的 HTTP 处理程序。

我想注意的另一件事是图像大小。您可以使用处理程序的ProcessRequest函数中的ADSSAntiBot公共构造函数轻松设置它。

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);
}

下图显示了此代码的结果。有时您想要一张大图像,有时想要一张小图像。

Screenshot - large_captcha.jpg

关注点

那么,我们是如何创建这种“难以 OCR”的图像的?我们如何改进它?

我们使用GraphicsPath来包裹图像。基本上,转换是一个正弦波、规则的随机噪声和一些旋转。目标是什么?创建可以被人类阅读而不是被机器人阅读的文本。我们如何做到这一点?我们“摇动”文本的子路径。

转换的目标是什么?首先,我们需要改变它以使字母分离变得困难。为此,我们添加一条贯穿所有显示的数字的线。其次,我们需要记住,使用神经网络的 OCR 应该难以识别我们的数字。通过随机移动路径点并使用正弦波,我们使线条在某些地方非常粗。在示例图像中,您可以在“9”和“6”上看到这种效果。

以下函数是我们转换的核心

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;
}

我们不像其他人那样使用很多字体,也不使用颜色。颜色模型仅有助于 OCR 识别许多验证码;字体也不是障碍。但在这里,我们正在使用这个包裹制作一个“随机”字体。我只是想表明,.NET Framework 使保护站点免受机器人侵害的可能性比其他框架要好得多。此外,我对您关于非验证码机器人防护的建议感兴趣。我将继续在这方面进行研究。

历史

本文中描述的代码是完全免费的。您可以在线尝试它。

此外,您可以从 ADSS 网站下载最新版本。随意基于此创建您的验证码来对抗垃圾邮件。

© . All rights reserved.