登录防刷离不开验证码。用 GDI+ 绘制验证码图片无需任何控件库,把随机字符、干扰线、噪点画到 Bitmap 上即可输出图片,方法完全独立,窗体或接口场景都能复用。
实现思路
新建指定尺寸的 Bitmap,Graphics 开抗锯齿;先画淡色干扰线,再用随机字体大小与颜色绘制字符,最后铺噪点像素。返回 Bitmap 后由调用方保存或输出。
完整代码
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
public static class CaptchaImage
{
public static Bitmap Generate(string code, int width = 130, int height = 42)
{
var bmp = new Bitmap(width, height);
var rnd = new Random();
using (var g = Graphics.FromImage(bmp))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
g.Clear(Color.FromArgb(245, 247, 250));
// 干扰线
for (int i = 0; i < 5; i++)
using (var pen = new Pen(Color.FromArgb(rnd.Next(170, 220), rnd.Next(170, 220), rnd.Next(170, 220)), 1.2f))
{
g.DrawLine(pen, rnd.Next(width), rnd.Next(height), rnd.Next(width), rnd.Next(height));
}
// 字符
using (var font = new Font("Arial", 24, FontStyle.Bold))
using (var brush = new SolidBrush(Color.FromArgb(40, 60, 90)))
{
float x = 8;
foreach (char c in code)
{
g.DrawString(c.ToString(), font, brush, x, 6);
x += 28;
}
}
// 噪点
for (int i = 0; i < 90; i++)
bmp.SetPixel(rnd.Next(width), rnd.Next(height), Color.FromArgb(170, 170, 170));
}
return bmp;
}
}
class Program
{
static void Main()
{
string code = "A8K3"; // 由随机算法生成并存 Session 校验
using (var bmp = CaptchaImage.Generate(code))
{
bmp.Save("captcha.png", ImageFormat.Png);
}
}
}增强方向
- 每个字符使用随机旋转与颜色,进一步提升 OCR 难度;
- 字符间加入随机粘连曲线代替直线,视觉效果更接近主流验证码;
- 服务端保存答案时应同时记录过期时间,防止验证码长期有效。
小结
GDI+ 画验证码逻辑简单、性能好,接口场景可把 Bitmap 转 MemoryStream 后输出为响应流,是 WinForms 与 ASP.NET 通用的写法。
评论(0)
暂无评论,快来抢沙发吧~