พอดีวันนี้ไปเจอ code Image Verifier
หรือ CAPTCHA ที่เว็บ
codeproject.com ซึ่งมีประโยชน์มากในการทดสอบผู้ที่กรอกแบบฟอร์มต่างๆ
ในเว็บไซต์ว่าเป็นมนุษย์หรือไม่ เพื่อที่สำหรับกัน bot หรือ
โปรแกรมอัตโนมัติต่างๆมา bomb หรือ ยิง เว็บไซต์เรานะครับ
ใน
codeproject.com ได้อธิบายขั้นตอนการทำเกี่ยวกับ CAPTCHA หรือ Image
Verifier นี้ ในรูปแบบของเว็บไซต์ีที่ถูกเขียนขึ้นจาก ASP.NET ธรรมดานะครับ
หรือเขียนจากเว็บฟอร์ม ซึ่ง จะเขียนในลักษณะของ user control
สามารถเข้าไปดูได้ที่ http://www.codeproject.com/KB/aspnet/ImageVerifier.aspx
ซึ่งวันนี้ ผมจะแนะนำไอเดียในการประยุกต์ใช้งานกับเพื่อนๆที่กำลังเล่น
ASP.NET MVC
อยู่เพื่อที่จะได้ไอเดียใหม่ๆในการประยุกต์ใช้งานมากยิ่งขึ้นครับ
เรา
มาเริ่มกันเลยดีกว่า
- สร้าง ImageResult สำหรับเก็บรูปภาพซึ่งถูก render จากตัว generater
หรือตัว random รูปภาพสำหรับทดสอบมนุุษย์นั่นเอง (จะกล่าวในข้อต่อไป)
1: public class ImageResult : ActionResult
2: {
3: public Image Image { get; set; }
4:
5: public override void ExecuteResult(ControllerContext context)
6: {
7: context.HttpContext.Response.Clear();
8: context.HttpContext.Response.ContentType = "image/Jpeg";
9: Image.Save(context.HttpContext.Response.OutputStream, ImageFormat.Jpeg);
10: }
11:
12: }
- สร้าง ImageController สำหรับ generate รูปภาพ และบันทึก รหัสลับลงไปใน
Cache โดยจะทำการตรวจเช็คอีกที โดยรหัสลับนี้จะมี index
ประจำตัวของรหัสลับโดยสร้างจาก Guid (Globally Unique Identifier)
ซึ่งเป็นชุดตัวเลขผสมตัวอักษรไม่ซ้ำกันขนาด16 bytes และโดย default ของ
Controller แล้้วให้เรียกใช้งานที่ Action ชื่อ Index ครับ
1: public class ImageController : Controller
2: {
3:
4: public ActionResult Index(string uid)
5: {
6: Bitmap bmp = new Bitmap(180, 40);
7: Graphics g = Graphics.FromImage(bmp);
8: string randString = GetRandomText(); // สร้างชุดรหัสลับขึ้นมาด้วยการ random
9:
10: this.HttpContext.Cache.Add(uid, randString, null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(5), System.Web.Caching.CacheItemPriority.Normal, null); // เก็บลง Cache สำหรับการตรวจเช็คโดยการ submit form
11:
12: // สร้างลวดลายสำหรับกันโปรแกรมอัตโนมัติ
13: g.FillRectangle(Brushes.WhiteSmoke, 0, 0, 180, 40);
14: g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default;
15: g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
16:
17: Random rand = new Random();
18: for (int i = 0; i < randString.Length; i++)
19: {
20: Font drawFont = new Font("Arial", 18, FontStyle.Italic | (rand.Next() % 2 == 0 ? FontStyle.Bold : FontStyle.Regular));
21: g.DrawString(randString.Substring(i, 1), drawFont, Brushes.Black, i * 35 + 10, rand.Next() % 12);
22: }
23:
24: Point[] pt = new Point[15];
25: for (int i = 0; i < 15; i++)
26: {
27: pt[i] = new Point(rand.Next() % 180, rand.Next() % 35);
28: g.DrawEllipse(Pens.LightSteelBlue, pt[i].X, pt[i].Y, rand.Next() % 30 + 1, rand.Next() % 30 + 1);
29: }
30:
31: // returm Result ออกมาเป็นชนิดข้อมูลแบบรูปภาพครับ
32: return new ImageResult { Image = bmp };
33: }
34:
35: // เป็น method สำหรับ random รหัสลับ
36: private string GetRandomText()
37: {
38: string uniqueID = Guid.NewGuid().ToString();
39: string randString = "";
40: for (int i = 0, j = 0; i < uniqueID.Length && j < 5; i++)
41: {
42: char l_ch = uniqueID.ToCharArray()[i];
43: if ((l_ch >= 'A' && l_ch <= 'Z') || (l_ch >= 'a' && l_ch <= 'z') || (l_ch >= '0' && l_ch <= '9'))
44: {
45: randString += l_ch;
46: j++;
47: }
48: }
49: return randString;
50: }
51:
52: }
วิธีใช้งาน
ในหัวข้อนี้จะเป็น วิธีการใช้งานนะครับ หลักการก็คือเราจะเขียน tag HTML เพื่อเรียกชื่อไฟล์รูปธรรมดาๆ แต่ไฟล์รูปนั้นจะเป็น url ของ ImageController ครับ เนื่องจาก ImageController จะ return ImageResult ออกมาซึ่งจะได้เป็นรูปที่ random รหัสลับออกมาแล้ว ลองมาดูตัวอย่างกันเลยครับ
- อันดับแรก สร้าง Home Controller และ เขียน code สร้าง Guid กำกับ รูปที่ถูกสร้างขึ้น (สำหรับการตรวจเช็ค) ซึ่งในที่นี้ผมจะแสดงเฉพาะ action Index ของ Home Controller นะครับ
1: public ActionResult Index()
2: {
3: string guid = Guid.NewGuid().ToString(); // สร้าง Guid
4: ViewData["guidimageverify"] = guid; // เก็บ guid ลง ViewData สำหรับแสดงผลที่ View
5: return View();
6: }
- ต่อไปเราจะเอา Guid จาก ViewData มาแสดงลงในรูปแบบของ image html tag
เพื่อแสดงรูปครับ
1: <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>
2: <asp:Content ID="indexTitle" ContentPlaceHolderID="TitleContent" runat="server"> Home Page</asp:Content>
3: <asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
4:
5: <%using (Html.BeginForm()){ %>
6:
7: <%=String.Format("<img alt=\"ImageVerifier\" src=\"Image?uid={0}\">", ViewData["guidimageverify"])%><br />
8: <%=Html.Hidden("uidImageVerify",ViewData["guidimageverify"]) %><br />
9: <%=Html.TextBox("txtImageVerify") %><br /><input type="submit" value="Submit"/>
10:
11: <%} %>
12:
13: </asp:Content
- ทีนี้เราก็จะได้รูปที่ถูก random และเก็บลง Cache โดยมี Guid ดังรูปครับ
การเช็ครหัสลับ
การเช็ครหัสทำ
ได้ง่ายมากครับโดยการสร้าง Action Index โดยกำกับ ด้วย
[AcceptVerbs(HttpVerbs.Post)] คือ เป็น Action หลังจากการ Post Form
จากหน้า View Index ครับ โดยมีการเช็คกับ Cache ด้วย guid และ ค่า จาก
textbox ครับลองดูตัวอย่างตามนี้เลยครับ
1: [AcceptVerbs(HttpVerbs.Post)]
2: public ActionResult Index(string uidImageVerify, string txtImageVerify)
3: {
4: string value = string.Format("{0}", this.HttpContext.Cache[uidImageVerify]); // เรียกค่ารหัสลับจาก Cache มาเพื่อเช็คกับ textbox
5:
6: if (value == txtImageVerify)
7: {
8: return View("Success"); // ถ้ารหัสถูกต้อง ไปที่ view ชื่อ Success
9: }
10:
11: return RedirectToAction("Index"); // รหัสลับไม่ถูกต้อง กลับไปที่หน้า index เพื่อกรอกรหัสใหม่
12: }
จบแล้วครับ เป็นไงบ้างครับ พอที่จะได้ไอเดียในการกันโปรแกรมอัตโนมัติต่างๆ
หรือ bot แล้วนะครับ เพื่อนๆลองนำไอเดียนี้ไปใช้ได้หรืออาจจะมีวิธีอื่นๆ
นอกจากเก็บรหัสลง Cache เช่นเพิ่ม Algorithm หรือการ encryption ต่างๆ
เพื่อเพิ่มความปลอดภัยก็ได้นะครับ : )
edit @ 6 Apr 2010 15:02:57 by oPoKo