CAPTCHA Image


Một CAPTCHA (ˈkæptʃə, đọc giống như “capture”) là một loại kiểm thử dạng hỏi đáp được dùng trong máy tính để xác định xem người dùng có phải là con người hay không. “CAPTCHA” là một dạng sắp đặt chữ đầu của “Completely Automated…

Một CAPTCHA (ˈkæptʃə, đọc giống như “capture”) là một loại kiểm thử dạng hỏi đáp được dùng trong máy tính để xác định xem người dùng có phải là con người hay không. “CAPTCHA” là một dạng sắp đặt chữ đầu của “Completely Automated Public Turing test to tell Computers and Humans Apart” (Phép thử Turing công cộng hoàn toàn tự động để phân biệt máy tính với người), được trường Đại học Carnegie Mellon giữ thương hiệu. Đây là một quá trình một máy tính (máy chủ) yêu cầu một người dùng hoàn tất một kiểm tra đơn giản mà máy tính có thể dễ dàng tạo ra và đánh giá, nhưng không thể tự giải nó được. Vì máy tính không thể giải quyết CAPTCHA, bất kỳ người dùng nào nhập vào lời giải đúng sẽ được xem là con người.

Bạn có thể bắt gặp những việc kiểm tra này khi đăng kí một email trực tuyến hoặc một tài khoản diễn đàn. Biểu mẫu đăng kí có thể có một ảnh chứa dòng chữ ngoằn nghèo như bạn thấy ở trên đây, và nó yêu cầu bạn phải gõ đúng vào ô nhập xác nhận.

Ý tưởng của việc làm này là nhằm ngăn ngừa các spammer sử dụng các web bot để tự động post dữ liệu vào form để tạo các tài khoản email (cho mục đích gửi spam). hoặc để đưa các feedback comment hay các bài viết mang mục đích spam. Dòng văn bản bên trong ảnh thường thường là nghuệch ngoạc để ngăn việc sử dụng các phần mềm OCR (chương trình đọc kí tự quang học) để hủy bỏ việc xử lý này. Hotmail, PayPal, Yahoo và nhiều các site đều sử dụng kỹ thuật này.

Bài viết này sẽ chỉ cho các bạn cách tạo những hình ảnh này và vận dụng nó vào trong trang web ASPX.

Cơ sở lý thuyết:

Khi bạn sử dụng kỹ thuật này vào trong trang web của mình thì hãy cân nhắc xem những đối tượng trong trang web của bạn có phù hợp với những người thị giác kém hoặc mù không. Điều này có thể gây ảnh hưởng đến khả năng sử dụng việc đưa CAPTCHA của bạn. PayPal cố gắng đã giải quyết vấn đề này bằng cách đưa thêm vào một link trỏ đên đoạn audio để đánh vần các dòng chữ trong ảnh đó.

Đoạn code ở đây chỉ sinh ra một hình ảnh. Nhưng nếu bạn có code để sinh ra một file audio thì bạn cũng có thể ghép lại vào một cách dễ dàng.

Viết mã:

Bạn tạo một ứng dụng web và thêm các file sau:
– CaptchaImage.cs –  đối tượng này sẽ tạo ra các hình ảnh.
– Default.aspx, Default.aspx.cs – a sample web form.
– JpegImage.aspx, JpegImage.aspx.cs – trang web xuất ra file ảnh JPEG.

Chúng ta hãy xem xét mỗi thành phần và mục đích của nó:

CaptchaImage.cs

Đối tượng này tạo ra một hình ảnh với các tham số cho đoạn text hiển thị như kích thước(tùy chọn), font chữ. Phần mã quan trọng nhất trong đối tượng này là phương thức GenerateImage() sẽ chỉ ra dưới đây, nó sẽ tạo ra một ảnh dạng bitmap với độ rộng và chiều dài được chỉ ra. Phương thức này được gọi ra từ hàm khởi tạo CaptchaImage, để ảnh được sẵn sàng ngay khi bạn tạo ra một instance của đối tượng.

Để tạo ảnh, đầu tiên chúng ta fill cho background bằng cách chải cho nó thật tối (ảnh xuất hiện càng “bẩn” thì chương trình OCR càng khó đọc được nó).

Để tạo ra đoạn text vừa vặn trong ảnh, chúng ta bắt đầu với kích thước font ban đầu dựa trên kích thước chiều cao ảnh và sử dụng phương thức Graphics.MeasureString() để tìm ra được kích thước phù hợp để vẽ đoạn text. Nếu như đoạn text vượt quá các kích thước của ảnh thì chúng ta phải giảm font chữ xuống và thử đi thử lại cho đến khi phù hợp với kích thước có thể nhận ra được.

Code
// ====================================================================
// 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;
}
Khi font được thiết lập, chúng ta định nghĩa phương thức GraphicsPath() để chuyển đổi đoạn text sang tập các đường thẳng và các đường cong. Đoạn text này có thể bị méo mó đi bằng cách dùng phương thức GraphicsPath.Warp() với một vài giá trị phát sinh ngẫu nhiên. Hiệu ứng giống như việc giữ tấm bìa cứng đánh dấu bởi các góc đối diện và làm no hơi bẻ xoắn đi một chút. Đường kẻ được vẽ ra trên tấm ảnh, rồi sử dụng bút chải cho nó xuất hiện “bẩn” đi chút.Để hoàn tất việc méo mó, vấy bẩn lên ảnh đó một số điểm ngẫu nhiên. Bạn có thể đã xem qua một số các hiệu ứng để cản trở các OCR, nhưng hãy nhớ rằng nên để nó có thể nhìn được, và một số người kém thị giác nữa.

Default.aspx.

Đây là một trang web mẫu đơn giản chỉ chứa một số các phần tử cơ bản, cụ thể là một thẻ <IMG> cho ảnh hiển thị, một textbox và một nút Submit.

<form id=”Default” method=”post” runat=”server”>       <img src=”JpegImage.aspx”><br>       <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, reload the page to generate a new one.)</em>       </p>       <p><asp:Label id=”MessageLabel” runat=”server”></asp:Label></p>     </form>

Để ý thuộc tính src của ảnh chỉ đến trang JpegImage.aspx.

Phần code cho trang Default.aspx đơn giản chỉ là việc sinh ra một chuỗi ngẫu nhiên cho ảnh và xác nhận tính hợp lệ của đoạn text này khi người dùng nhập vào ô text và nhấn vào nút Submit form. Khóa để lưu chuỗi text này là một đối tượng Session, bởi vì chúng ta còn phải truy cập đến trang JpegImage.aspx nữa.

private void 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();         }       }     }

JpegImage.aspx

Trong trang này, chúng ta không cần đến thẻ HTML nào cả (những gì cần làm ở đây chỉ là đoạn mã được sinh ra bởi Visual Studio khi file được tạo ra). Thay vì viết mã HTML, đoạn mã sẽ sinh ra một ảnh JPEG.

Trong phần mã , chúng ta đầu tiên tạo ra đối tượng Captcha, sử dụng ngay đoạn text lấy về từ đối tượng Session và tạo ra ảnh bitmap cho chúng ta.

private void 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();     }
Tiếp đến chúng ta chỉnh sửa phần header của HTTP response để thiết lập Content-type thành “image/jpeg” để trình duyệt máy người dùng sẽ biết luồng file đưa đến là định dạng JPEG. May mắn là phương thức Save của đối tượng Bitmap làm cho điều này thật đơn giản. Bất kể là định dạng file ảnh được hỗ trợ khác cũng sử dụng cách thiết lập tương ứng trong phần Content-type header này.

Bước cuối cùng là để lấy ra hình ảnh bitmap từ  CaptchaImage.Image và ghi nó vào luồng ra HTTP response theo định dạng JPEG.

Bởi vì lớp CaptchaImage chứa đối tượng Bitmap, và các bitmap vận dụng mã không quản, nên phương thức Dispose được thực hiện. Điều này cho phép các mã nguồn không quản được giải phóng bất cứ khi nào CaptchaImage bị hủy.

[HaiPhong-Aptech]

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s