2010年6月4日 星期五

圖形驗證(3): ASP.NET 圖形加強版

(1) 簡介(2): ASP.NET 簡易實作圖形驗證後,這次針對圖形太簡單的問題再做加強。

加強1

底色換成亂數取色。為了亂數取色,我寫了一個 extension method,延伸了 Random

using System;
using System.Drawing;

namespace Captcha.Utility
{
  public static class RandomExtension
  {
    /// <summary>
    /// 取得下一個顏色
    /// </summary>
    /// <param name="random"></param>
    /// <returns></returns>
    public static Color NextColor(this Random random)
    {
      return Color.FromArgb(random.Next(255), random.Next(255), random.Next(255));
    }
  }
}

因此,可以在換底色時,改成亂數取色。

//重新繪圖
Random r = new Random();
graphics = Graphics.FromImage(bmpImage);
graphics.Clear(r.NextColor()); //使用亂數底色
graphics.TextRenderingHint = TextRenderingHint.AntiAlias;  //不要鋸齒

加強2

讓字型大小也能亂數忽大忽小,並且就亂數取色,我將部份程式修改如下

int avgWidth = width / imageText.Length;
for (int i = 0; i < imageText.Length; i++)
{
font = new Font("Verdana", r.Next(12, 24), FontStyle.Bold, GraphicsUnit.Point);
graphics.DrawString(imageText.Substring(i, 1), font, new SolidBrush(r.NextColor()), avgWidth * i, 0); //把文字畫上去
}

加強3

最後,我再加強甘擾,讓機器人更難以進行 AntiCaptcha,我畫了10條粗細長度顏色不一的線。程式如下

private static void DrawRandomLine(Graphics graphics, int height, int width, Random random)
{
  Pen pen = new Pen(random.NextColor());
  pen.Width = random.Next(3);
  Point p1 = new Point(random.Next(width), random.Next(height));
  Point p2 = new Point(random.Next(width), random.Next(height));
  graphics.DrawLine(pen, p1, p2);
}
...
for (int i = 0; i < 10; i++)
        DrawRandomLine(graphics, height, width, r);

結果

以下是這三個步驟加強後的結果.還不錯呢!

image

結論

看起來不錯,但仍有些美中不足的部份。例如字的顏色如果很接進底色的話,使用者就看不出來了。此時必須讓使用者自行換圖,或者想辦法讓兩者的顏色差異變大。這些小加強就請讀者自行發揮了。

範例程式下載

2 則留言:

匿名 提到...

請問..如果在VS2005裡開發的話..可以怎麼修改呢?..謝謝~~

秉程 提到...

請自行以VS2005 建立一個 Web application,再將範例程式從頭到尾加入 web application 即可。

Share with Facebook