首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 發現之旅第九講:ASP.NET 驗證碼技術原理與實作

     編輯:關於C#

驗證碼技術背景:防禦枚舉字典攻擊

Web 系統面臨嚴峻安全挑戰,常見攻擊為「枚舉字典暴力破解」:駭客取得帳號後,編寫程式模擬瀏覽器透過 HTTP 協定高速嘗試密碼組合(如 6 位數字僅 100 萬種),若無防禦機制,單機每秒測試 10 次,約 27 小時即可破解。傳統用戶端防禦(ActiveX、USB 金鑰、客戶端程式)終究在駭客控制的環境中可被逆向分析繞過,根本不可靠。

驗證碼核心原理:人腦與電腦能力的非對稱性

驗證碼利用「電腦擅長邏輯運算、不擅長圖像識別;人腦擅長圖像識別、不擅長高頻重複勞動」的差異:

  1. 伺服器生成包含隨機扭曲字符、干擾雜點的圖片(驗證碼媒介),正確答案儲存在 Session 中。
  2. 用戶登入時必須辨識圖片字符並輸入。
  3. 伺服器驗證輸入與 Session 值是否一致。

駭客程式無法自動識別圖片,只能人工逐張辨識輸入,將原本自動化的百萬次嘗試轉為人工操作,成本極高,有效癱瘓枚舉攻擊。合成語音、表情辨識等同理可作為替代媒介。

ASP.NET 實作完整流程

圖片服務頁面 checkimage.aspx

專責生成驗證碼圖片,無 HTML 輸出,Page_Load 執行核心邏輯:

// 1. 產生隨機驗證碼文字 (4-6 碼英數)
Random rand = new Random();
int len = rand.Next(4, 6);
char[] chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
StringBuilder myStr = new StringBuilder();
for (int i=0; i<len; i++) myStr.Append(chars[rand.Next(chars.Length)]);
string text = myStr.ToString();
Session["checkcode"] = text; // 儲存供驗證

// 2. 計算圖片尺寸
Size ImageSize = Size.Empty;
Font myFont = new Font("MS Sans Serif", 20);
using (Bitmap bmp = new Bitmap(10,10))
using (Graphics g = Graphics.FromImage(bmp)) {
    SizeF size = g.MeasureString(text, myFont, 10000);
    ImageSize.Width = (int)size.Width + 8;
    ImageSize.Height = (int)size.Height + 8;
}

// 3. 繪製驗證碼文字
using (Bitmap bmp = new Bitmap(ImageSize.Width, ImageSize.Height))
using (Graphics g = Graphics.FromImage(bmp)) {
    g.Clear(Color.White);
    using (StringFormat f = new StringFormat()) {
        f.Alignment = StringAlignment.Near;
        f.LineAlignment = StringAlignment.Center;
        f.FormatFlags = StringFormatFlags.NoWrap;
        g.DrawString(text, myFont, Brushes.Black, 
            new RectangleF(0,0,ImageSize.Width,ImageSize.Height), f);
    }
    // 4. 製造噪點 (佔 30% 面積)
    int num = ImageSize.Width * ImageSize.Height * 30 / 100;
    for (int i=0; i<num; i++) {
        int x = rand.Next(ImageSize.Width);
        int y = rand.Next(ImageSize.Height);
        Color c = Color.FromArgb(rand.Next(255), rand.Next(255), rand.Next(255));
        bmp.SetPixel(x, y, c);
    }
    // 5. 輸出 PNG 串流
    MemoryStream ms = new MemoryStream();
    bmp.Save(ms, ImageFormat.Png);
    Response.ContentType = "image/png";
    ms.WriteTo(Response.OutputStream);
    ms.Close();
}
myFont.Dispose();

靜態驗證方法

public static bool CheckCode(string text) {
    string txt = HttpContext.Current.Session["checkcode"] as string;
    return text == txt;
}

登入頁面 login.aspx

登入頁面介面

介面含帳號、密碼、驗證碼三輸入框,驗證碼輸入框旁放置 <img src="checkimage.aspx"> 顯示圖片。登入按鈕邏輯:

private void cmdOK_Click(object sender, EventArgs e) {
    string UserName = txtUserName.Text;
    string Password = txtPassword.Text;
    string CheckCode = txtCheckCode.Text;
    if (UserName == "張三" && Password == "abc" && checkimage.CheckCode(CheckCode)) {
        lblResult.Text = "<b>登入成功</b>";
        RegisterStartupScript("a", "<script>alert('登入成功');</script>");
    } else {
        lblResult.Text = "<font color=red><b>登入資訊錯誤,請重新輸入</b></font>";
    }
}

使用者體驗優化:雙擊更換驗證碼

若圖片難以辨識,用戶可雙擊圖片重新載入:

<img src="checkimage.aspx" 
     title="看不清楚,雙擊圖片換一張。"
     ondblclick="this.src = 'checkimage.aspx?flag=' + Math.random()"
     border="1">

ondblclick 附加隨機 flag 參數強制瀏覽器繞過快取重新請求,伺服器重新生成驗證碼文字與圖片,Session 同步更新,安全性與易用性並重。

安全性與可用性權衡

驗證碼大幅提升安全性,但增加用戶操作步驟、降低可用性(特別是視障用戶)。實務應根據系統風險等級、用戶群體特性決定是否啟用、採用何種強度(字元長度、干擾程度)、是否提供語音替代方案等。

小結

本講透過驗證碼案例,展示圖形程式設計在 Web 安全領域的關鍵應用。核心技術包含:System.Drawing 動態生成圖片、Graphics.MeasureString 計算尺寸、DrawString 繪製文字、SetPixel 製造噪點、MemoryStream 串流輸出、Session 跨請求狀態保持。圖形程式設計應用廣泛,為多種技術提供底層支撐。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved