验证码图像

分享于 

11分钟阅读

Web开发

  繁體

Sample Image - CaptchaImage.gif

介绍

of代表"完全自动化的public 图灵测试来区分计算机和人类。"的意思是,一个可以使用某种类型的生成测试来告诉人们的程序。 大多数人很容易通过,但电脑程序却不能。

你在注册在线电子邮件或者论坛帐户时可能遇到过这样的测试。 表单可能包含像上面看到的扭曲文本的图像,你需要在文本字段中输入。

目的是防止垃圾邮件发件人使用网络机器人自动发布表单数据,以便创建电子邮件帐户( 发送垃圾邮件) 或者提交反馈意见或者包含垃圾邮件消息的电子邮件条目。 图像中的文本通常被扭曲,以防止使用 OCR ( 光学字符识别器) 软件来破坏进程。 Hotmail。贝宝。雅虎和许多博客网站都采用这种技术。

本文演示如何创建这样的图像并在 ASP.NET web窗体中使用它。

背景

You Baffling CAPTCHA Project Project Project Project Project Project Project Project Project Project Project Project Project Project Project Project Project Project Project Project。

然而,在使用这里技术之前,应该考虑如何影响到盲人和它的他视觉受损访问者的可以访问性。 贝贝试图在他们的签名表单上解决这个问题,包括一个音频文件的链接。

这里提供的代码只生成图像。 但是,如果你有生成音频文件的代码,你可以轻松地集成它。

使用代码

源代码zip文件包含一个类和两个web窗体的源。 要使用它,只需创建一个新的web项目并。

文件

  • CaptchaImage.cs - 定义实际创建图像的CapchaImage 对象。
  • Default.aspx,Default.aspx. cs - 一个示例网页表单。
  • jpegimage cs JpegImage.aspx. cs cs - 一种用于输出JPEG图像而不是HTML的网页表单。

让我们看看每个组件,它是目的。

CaptchaImage.cs

CaptchaImage 对象为要显示的文本。图像尺寸以及可以选择使用的字体创建一个给定的图像参数。

代码的核心是 GenerateImage() 方法,显示 below,它创建指定宽度和高度的位图图像。 这里方法从 CaptchaImage 构造函数调用,因此只要你创建对象的新实例,图像就已经准备好了。

要创建图像,我们首先使用一个填充画笔("dirtier"图像出现时,OCR程序读取它的难度就越大。) 填充 background。

为了使文本适合于图像,我们从基于图像高度的初始字体大小开始,使用 Graphics.MeasureString() 方法查找文本。 如果文本超出图像尺寸,我们将缩小字体大小并反复测试,直到找到合适的字体大小。

// ====================================================================// Creates the bitmap image.// ====================================================================privatevoid 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;
}

一旦设置了字体,我们就定义了一个 GraphicsPath(),它实质上将文本转换为一组线条和曲线。 然后,可以使用 GraphicsPath.Warp() 方法和一些随机生成的值来扭曲。 这种效果类似于把一个纸板贴在相反的角落,并给它一点扭曲。 将生成的路径绘制到图像上,再次使用图案填充画笔为它的提供"dirty"外观。

为了完成变形,在图像上随机绘制小的小孔。 你可以试试它的他效果来阻止 OCRs,但要记住,它仍然可以对人类有所解释。

Default.aspx

这是一个非常简单的示例web表单,只包含几个基本元素,即 <> 图像,文本框和"提交"按钮的标记。

<formid="Default"method="post"runat="server"><imgsrc="JpegImage.aspx"><br><p><strong>Enter the code shown 上面:</strong><br><asp:TextBoxid="CodeNumberTextBox"runat="server"></asp:TextBox><asp:Buttonid="SubmitButton"runat="server"Text="Submit"></asp:Button><br></p><p><emclass="notice"> (Note: If you cannot read the numbers in the 上面<br> image, reload the page to generate a new one.)</em></p><p><asp:Labelid="MessageLabel"runat="server"></asp:Label></p></form>

请注意 SRC 属性 <> 标记指向web窗体 JpegImage.aspx。

代码后面的代码只是为图像生成随机文本字符串并验证当表单提交时用户输入的文本。 关键是将文本字符串存储在 Session 对象中。

privatevoid Page_Load(object sender, System.EventArgs e)
{
 if (!this.IsPostBack)
 // Create a random code and store it in the Session object.this.Session["CaptchaImageText"] = GenerateRandomCode();
 else {
 // On a postback, check the user input.if (this.CodeNumberTextBox.Text ==
 this.Session["CaptchaImageText"].ToString())
 {
 // Display an informational message.this.MessageLabel.CssClass = "info";
 this.MessageLabel.Text = "Correct!";
 }
 else {
 // Display an error message.this.MessageLabel.CssClass = "error";
 this.MessageLabel.Text = "ERROR: Incorrect, try again.";
 // Clear the input and create a new random code.this.CodeNumberTextBox.Text = "";
 this.Session["CaptchaImageText"] = GenerateRandomCode();
 }
 }
}

为了在 Session 对象中存储文本字符串的原因,它可以被 JpegImage.aspx 访问。

JpegImage.aspx

对于这个网页表单,不需要任何 HTML。 代码将生成一个JPEG图像,而不是 HTML。

在后面的代码中,我们首先创建一个 CaptchaImage 对象,使用从 Session 对象检索到的文本。 这将为我们创建一个位图图像。

privatevoid Page_Load(object sender, System.EventArgs e)
{
 // 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();
}

然后修改HTTP响应头以设置 Content-Type 到"图像/jpeg",这样客户端浏览器就会知道我们发送图像。

最后一步是从 CaptchaImage.Image 检索位图图像,并将它的写到JPEG格式的HTTP响应输出流中。 幸运的是,Bitmap 对象的Save() 方法使得这个简单。 任何它的他受支持的图像格式也可以使用,因这里只要相应地设置 Content-Type header。

Points of Interest

由于 CaptchaImage 类包含 Bitmap 对象,位图采用非托管资源,因此将实现自定义 Dispose() 方法。 这允许在销毁 CaptchaImage 时释放那些非托管资源。

历史记录

January 26,2004 - 版本 1.0

  • 初始版本。

2年月,2004 - 版本 1.01

  • CaptchaImage.SetDimensions() 中更正参数检查的小修正。

图像  cap  验证码  
相关文章