傳統數字/字母驗證碼易被 OCR 識別,騰訊等大廠曾採用中文漢字驗證碼提升安全性。本文詳細解析基於 GB2312 區位碼隨機生成常用漢字的原理,並提供完整控制台示例代碼。
GB2312-80 將漢字編排在 94 個區、每區 94 位,共 8836 個碼位,其中一級漢字 3755 個(按拼音排序)、二級漢字 3008 個(按部首/筆畫排序)。
例如「好」字區位碼 26區35位 → 區碼 0xB0+25=0xC9? 實際查表為 0xBA 0xC3(原文示例)。
並非所有碼位均為常用漢字,需排除:
因此隨機範圍限定為:
獲取 GB2312 編碼器,核心方法:
GetBytes(string):字符串 → 字節數組GetString(byte[]):字節數組 → 字符串
public static byte[] GenerateValidGb2312Char(Random rnd)
{
// 高字節:0xB0(176) 到 0xD6(214)
int high = rnd.Next(0xB0, 0xD7); // [176, 214]
int low;
if (high == 0xD7) // 第 55 區特殊處理
low = rnd.Next(0xA1, 0xF7); // 0xA1-0xF6
else
low = rnd.Next(0xA1, 0xFF); // 0xA1-0xFE
// 排除每區首尾空碼 (簡化處理)
if (low == 0xA1 || low == 0xFE) low = 0xA2;
return new byte[] { (byte)high, (byte)low };
}
using System;
using System.Text;
class ChineseCaptcha
{
static Random rnd = new Random();
static void Main()
{
Encoding gb = Encoding.GetEncoding("gb2312");
int count = 4;
string captcha = "";
for (int i = 0; i < count; i++)
{
byte[] bytes = GenerateValidGb2312Char(rnd);
string ch = gb.GetString(bytes);
// 過濾掉可能生成的控制字符或亂碼
if (IsValidHanzi(ch))
captcha += ch;
else
i--; // 重試
}
Console.WriteLine($"生成驗證碼: {captcha}");
// 後續可用 GDI+ 繪製干擾線、扭曲、噪點生成圖片
}
static bool IsValidHanzi(string s)
{
// 簡單判斷:是否為 CJK 統一表意文字基本區塊
foreach (char c in s)
if (c < 0x4E00 || c > 0x9FFF) return false;
return true;
}
static byte[] GenerateValidGb2312Char(Random rnd) { /* 同上 */ }
}
Bitmap、Graphics,設置 SmoothingMode、TextRenderingHintDrawLine、DrawCurve(貝塞爾曲線)FillRectangle 1x1 像素image/png 或保存文件Microsoft.AspNetCore.Antiforgery + 前端圖形驗證碼庫 (如 captcha-com)理解 GB2312 區位碼結構是生成中文驗證碼的關鍵。通過限定高低字節範圍、過濾空碼,配合 Encoding.GetString 解碼,即可獲得常用漢字。實際部署時務必結合圖形干擾、會話綁定、限流等措施,或直接採用成熟的行為驗證服務。