頁面需驗證碼防止惡意提交。方案:WebService 方法回傳驗證碼圖片位元組陣列 (`byte[]`),前端 `` 標籤指向 `.asmx` 或 `.ashx` 取得圖片,驗證碼文字存入 Session 驗證。
[WebService(Namespace = "https://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService] // 允許 AJAX 呼叫
public class VerifyCodeService : System.Web.Services.WebService
{
[WebMethod(EnableSession = true)] // 需啟用 Session
public byte[] GenerateVerifyImage(int length, out string verifyCode)
{
// 1. 參數檢查
if (length < 1 || length > 10) length = 4;
// 2. 產生隨機驗證碼
const string chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"; // 排除易混淆字元
var rand = new Random();
var codeChars = new char[length];
for (int i = 0; i < length; i++) codeChars[i] = chars[rand.Next(chars.Length)];
verifyCode = new string(codeChars);
// 3. 儲存至 Session (供後續驗證)
Context.Session["VerifyCode"] = verifyCode.ToUpper();
// 4. 繪製圖片
int width = 13 * length + 10;
int height = 28;
using (var bmp = new Bitmap(width, height))
using (var g = Graphics.FromImage(bmp))
{
// 背景
g.Clear(Color.White);
// 干擾線
for (int i = 0; i < 5; i++)
{
using (var pen = new Pen(Color.FromArgb(rand.Next(160, 255), rand.Next(160, 255), rand.Next(160, 255))))
{
g.DrawLine(pen, rand.Next(width), rand.Next(height), rand.Next(width), rand.Next(height));
}
}
// 干擾點
for (int i = 0; i < 50; i++)
{
bmp.SetPixel(rand.Next(width), rand.Next(height), Color.FromArgb(rand.Next(256), rand.Next(256), rand.Next(256)));
}
// 文字
using (var font = new Font("Consolas", 16, FontStyle.Bold | FontStyle.Italic))
using (var brush = new SolidBrush(Color.FromArgb(rand.Next(0, 100), rand.Next(0, 100), rand.Next(0, 100))))
{
for (int i = 0; i < length; i++)
{
float x = 5 + i * 13 + rand.Next(-1, 2);
float y = 2 + rand.Next(-1, 2);
g.DrawString(codeChars[i].ToString(), font, brush, x, y);
}
}
// 輸出為 byte[]
using (var ms = new MemoryStream())
{
bmp.Save(ms, ImageFormat.Gif);
return ms.ToArray();
}
}
}
[WebMethod(EnableSession = true)]
public bool ValidateVerifyCode(string userInput)
{
string code = Context.Session["VerifyCode"] as string;
if (string.IsNullOrEmpty(code)) return false;
return string.Equals(code, userInput?.ToUpper(), StringComparison.OrdinalIgnoreCase);
}
}
<img id="imgVerify" src="VerifyCodeService.asmx/GenerateVerifyImage?length=4" alt="驗證碼" style="cursor:pointer" onclick="this.src=this.src.split('?')[0]+'?length=4&t='+Date.now()" />
$.ajax({
type: "POST",
url: "VerifyCodeService.asmx/GenerateVerifyImage",
data: JSON.stringify({ length: 4 }),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (resp) {
// resp.d 為 base64 字串 (byte[] 自動轉換)
$("#imgVerify").attr("src", "data:image/gif;base64," + resp.d);
}
});
$.post("VerifyCodeService.asmx/ValidateVerifyCode", { userInput: $("#txtCode").val() }, function(resp) {
if (resp.d) { /* 通過 */ } else { /* 失敗,重新整理圖片 */ }
});
ASP.NET WebService 結合 `System.Drawing` 實作驗證碼服務,核心在於 `Bitmap` 繪圖、`MemoryStream` 序列化為 `byte[]`、Session 儲存驗證碼。雖 ASMX 屬舊技術,但原理通用於現代 ASP.NET Core 檔案流回傳與驗證邏輯。