using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Web.UI;
public partial class VerifyCode : Page
{
protected void Page_Load(object sender, EventArgs e)
{
// 防止快取
Response.Cache.SetNoStore();
Response.Cache.SetExpires(DateTime.MinValue);
GenerateImage();
}
private void GenerateImage()
{
const int width = 71, height = 23;
using (var bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb))
using (var g = Graphics.FromImage(bmp))
{
var rand = new Random();
// 1. 背景
g.Clear(Color.White);
// 2. 干擾線
for (int i = 0; i < 50; i++)
{
using (var pen = new Pen(Color.FromArgb(rand.Next(256), rand.Next(256), rand.Next(256))))
{
g.DrawLine(pen, rand.Next(width), rand.Next(height), rand.Next(width), rand.Next(height));
}
}
// 3. 干擾點
for (int i = 0; i < 100; i++)
{
bmp.SetPixel(rand.Next(width), rand.Next(height), Color.FromArgb(rand.Next(256), rand.Next(256), rand.Next(256)));
}
// 4. 產生隨機碼
string code = GenerateRandomCode(5);
Session["RandCode"] = code; // 存入 Session
// 5. 繪製文字
using (var font = new Font("Arial", 14, FontStyle.Bold))
using (var brush = new LinearGradientBrush(
new Rectangle(0, 0, width, height),
Color.Red, Color.Blue, 1.2f, true))
{
int yOffset = rand.Next(1, 4);
g.DrawString(code, font, brush, 2, yOffset);
}
// 6. 邊框
g.DrawRectangle(Pens.Silver, 0, 0, width - 1, height - 1);
// 7. 輸出
using (var ms = new MemoryStream())
{
bmp.Save(ms, ImageFormat.Gif);
Response.ClearContent();
Response.ContentType = "image/gif";
Response.BinaryWrite(ms.ToArray());
}
}
}
private static readonly char[] _chars = "0123456789abcdefghijklmnopqrstuvwxyz".ToCharArray();
private string GenerateRandomCode(int length)
{
var rand = new Random();
var sb = new StringBuilder(length);
for (int i = 0; i < length; i++) sb.Append(_chars[rand.Next(_chars.Length)]);
return sb.ToString();
}
}
<asp:Image ID="imgVerify" runat="server" ImageUrl="~/VerifyCode.aspx" Style="cursor:pointer; vertical-align:middle;" />
<a href="javascript:void(0);" onclick="document.getElementById('<%=imgVerify.ClientID%>').src='VerifyCode.aspx?t='+Date.now();">看不清?換一張</a>
<br />
<asp:TextBox ID="txtCode" runat="server" MaxLength="5" />
<asp:Button ID="btnSubmit" runat="server" Text="提交" OnClick="btnSubmit_Click" />
protected void btnSubmit_Click(object sender, EventArgs e)
{
string userCode = txtCode.Text.Trim().ToLower();
string sessionCode = (Session["RandCode"] as string)?.ToLower();
if (string.Equals(userCode, sessionCode))
{
lblResult.Text = "驗證通過!";
// 移除 Session 防止重複使用
Session.Remove("RandCode");
}
else
{
lblResult.Text = "驗證碼錯誤,請重新輸入。";
}
}
| 方向 | 做法 |
|---|---|
| 字型多樣化 | 隨機選擇字型、字體大小、旋轉角度 (`g.RotateTransform`) |
| 中文驗證碼 | 字元集改為常用漢字,字型需支援中文 (如「微軟正黑體」) |
| 語音驗證碼 | 產生語音檔 (TTS) 回傳 `audio/mp3`,無障礙支援 |
| 滑動/點選驗證 | 前端 Canvas/JS 互動,後端驗證軌跡/點選座標 |
| 分散式 Session | Web Farm 環境下使用 Redis/DB 儲存驗證碼,避免 InProc Session 遺失 |
ASP.NET 圖形驗證碼核心在於 `Bitmap` + `Graphics` 繪製、`Session` 狀態同步、`Response.BinaryWrite` 圖片流輸出。範例提供可直接部署的完整程式碼,並指出進階強化與生產環境注意事項。