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

ASP.NET 2.0 中文驗證碼(CAPTCHA)實作:GDI+ 繪圖、干擾線、Session 驗證

     編輯:關於ASP.NET

驗證碼是防止自動化腳本提交表單的基礎防線。ASP.NET 2.0 使用 System.Drawing (GDI+) 動態產生圖片,存入 Session 驗證。本文提供完整中文驗證碼實作:隨機中文字庫、干擾線、雜訊點、Session 儲存、HTTP 輸出圖片流。

驗證碼產生頁面:ValidateCode.aspx

<%@ Page Language="C#" %>
<%@ Import Namespace="System.Drawing" %>
<%@ Import Namespace="System.Drawing.Imaging" %>
<%@ Import Namespace="System.Drawing.Text" %>
<script runat="server">
    protected void Page_Load(object sender, EventArgs e)
    {
        // 1. 設定圖片尺寸
        int width = 100, height = 30;
        using (Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb))
        using (Graphics g = Graphics.FromImage(bitmap))
        {
            // 2. 背景填充
            g.Clear(Color.White);
            g.FillRectangle(new SolidBrush(Color.White), 0, 0, width, height);

            // 3. 字體設定(需伺服器安裝「標楷體」或「微軟正黑體」)
            Font font = new Font("標楷體", 16, FontStyle.Bold | FontStyle.Italic);
            // Font font = new Font("Microsoft JhengHei", 16, FontStyle.Bold);

            // 4. 產生 4 碼隨機中文驗證碼
            string[] chars = "我,是,沒,高,天,地,聊,材,盆,濁,小,涯,尖,欠,豬,左,腿,刀,吃,渴,棍,皮,影,歇,草,營,救,稅,說,壞,通,病,二,世,期,春,季,弄,刑,事,警,強,窩,菜,干,什,前,都,哭,拉,面,魚,文,鬼,或,熱,狗,蛋,毛,筆,網,件,構,試,社,幫,耐,燒,粘,蘋,鞋,板,裳,花,海,題,a,e,f,r,9,0,k,2,4,7,1,3,q,w,y,u,v,x,p,s,a,d,8,5,t".Split(',');
            Random rnd = new Random();
            string code = "";
            for (int i = 0; i < 4; i++)
                code += chars[rnd.Next(chars.Length)];
            
            Session["ValidateCode"] = code; // 存入 Session

            // 5. 繪製干擾背景:隨機矩形填充
            g.FillRectangle(new SolidBrush(Color.LightYellow), 0, 0, width, height);

            // 6. 繪製干擾線
            Pen pen = new Pen(Color.Gray, 1);
            for (int i = 0; i < 8; i++)
            {
                int x1 = rnd.Next(width), y1 = rnd.Next(height);
                int x2 = rnd.Next(width), y2 = rnd.Next(height);
                g.DrawLine(pen, x1, y1, x2, y2);
            }

            // 7. 繪製驗證碼文字(逐字元隨機位移、旋轉增加辨識難度)
            StringFormat sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };
            for (int i = 0; i < code.Length; i++)
            {
                Brush brush = new SolidBrush(Color.FromArgb(rnd.Next(100, 255), rnd.Next(100, 255), rnd.Next(100, 255)));
                float x = 10 + i * 22 + rnd.Next(-2, 3);
                float y = 15 + rnd.Next(-2, 3);
                g.TranslateTransform(x, y);
                g.RotateTransform(rnd.Next(-15, 15));
                g.DrawString(code[i].ToString(), font, brush, 0, 0, sf);
                g.ResetTransform();
            }

            // 8. 繪製雜訊點
            for (int i = 0; i < 50; i++)
            {
                int x = rnd.Next(width), y = rnd.Next(height);
                bitmap.SetPixel(x, y, Color.FromArgb(rnd.Next(256), rnd.Next(256), rnd.Next(256)));
            }

            // 9. 輸出圖片流
            Response.Clear();
            Response.ContentType = "image/jpeg";
            bitmap.Save(Response.OutputStream, ImageFormat.Jpeg);
        }
    }
</script>

前端使用方式

<img src="ValidateCode.aspx" id="imgCaptcha" alt="驗證碼" style="cursor:pointer; vertical-align:middle;" onclick="this.src='ValidateCode.aspx?'+Math.random()" />
<input type="text" id="txtCaptcha" name="txtCaptcha" maxlength="4" style="width:60px; ime-mode:disabled;" />
<a href="javascript:void(0);" onclick="document.getElementById('imgCaptcha').click()">看不清?換一張</a>

伺服器端驗證

protected void btnSubmit_Click(object sender, EventArgs e)
{
    string userInput = txtCaptcha.Text.Trim();
    string sessionCode = Session["ValidateCode"]?.ToString();
    
    if (string.IsNullOrEmpty(sessionCode))
    {
        lblMsg.Text = "驗證碼已過期,請重新整理";
        return;
    }
    
    if (string.Equals(userInput, sessionCode, StringComparison.OrdinalIgnoreCase))
    {
        lblMsg.Text = "驗證通過!";
        Session.Remove("ValidateCode"); // 一次性使用
        // 執行業務邏輯...
    }
    else
    {
        lblMsg.Text = "驗證碼錯誤";
        // 可選:記錄失敗次數、鎖定帳號
    }
}

進階強化建議

強化項目實作方式
字體多樣化隨機選擇「標楷體、微軟正黑體、新細明體、Arial」混合
文字扭曲變形使用 GraphicsPath.AddString + Matrix 仿射變換
背景漸層/圖片LinearGradientBrush 或載入背景圖片 g.DrawImage
語音驗證碼整合 TTS (System.Speech.Synthesis) 產生 .wav 提供無障礙存取
分散式 Session使用 Redis、SQL Server Session State、ASP.NET Core IDistributedCache
防暴力破解IP 限制請求頻率、驗證碼失效時間 (5-10 分鐘)、失敗 N 次鎖定

現代替代方案

  • reCAPTCHA v3 / hCaptcha:零互動風險評分、隱私友善、免費額度大。
  • 滑塊/點選/圖示驗證:Geetest、NetEase Captcha、阿里云驗證碼,體驗優於傳統輸入。
  • ASP.NET Core 中間件:app.UseCaptcha() 社區套件整合上述服務。

效能與部署注意

  • GDI+ 非執行緒安全,高併發下建議使用 lock 或改用 SkiaSharp、ImageSharp 跨平台庫。
  • 伺服器需安裝中文字體,Docker 映像需 RUN apt-get install -y fonts-wqy-zenhei (Linux) 或複製字體檔。
  • 輸出 image/jpeg 比 image/gif 壓縮率高、支援漸層色彩。
  • 加入 Response.Cache.SetNoStore() 防止瀏覽器快取驗證碼圖片。

結語

自製驗證碼適合學習 GDI+ 繪圖與 Session 機制,但生產環境強烈建議採用成熟第三方服務(reCAPTCHA、hCaptcha),安全性、可用性、無障礙、維運成本均更優。若必須自建,請參考上述進階強化項目並定期更新字庫與干擾策略。

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