0

0

.net封装一个验证码生成类

Y2J

Y2J

发布时间:2017-05-06 11:26:34

|

1881人浏览过

|

来源于php中文网

原创

本文和大家分享的是一个集成1:小写拼音;2:大写拼音;3:数字;4:汉字的验证码生成类。本章例子也会有一个mvc使用验证码校验的场景。具有一定的参考价值,下面跟着小编一起来看下吧

本次和大家分享的是一个集成1:小写拼音 2:大写拼音 3:数字 4:汉字的验证码生成类,从标题来看感觉很普通的样子,没错的确很普通,只是这个验证码类生成的时候可以通过参数指定验证码返回格式的规则,更主要的是希望能给大家带来一定的实用性,本章例子也会有一个mvc使用验证码校验的场景,希望大家能够喜欢。

» 验证码生成流程图

» 验证码生成池代码的解析

» 把验证代码画到图片

» mvc登录操作测试验证码正确性

下面一步一个脚印的来分享:

» 验证码生成流程图

首先,咋们来看一下本次分享的验证码生成类的生成流程图:

能看到此图描述的编码生成池对应的是几个不同的编码内容,这里主要根据参数设置允许同时获取不同编码内容,从而到达文字,拼音,汉字组合而成验证码,具体规则设置由参数而定;

» 验证码生成池代码的解析

首先,由上面流程图分析的内容能看出,这个验证码生成池子需要并行获取不同类型验证码数据,才能满足组合的验证码,因此有了下面的代码:

/// 
 /// 创建验证码
 /// 
 /// 1:小写拼音 2:大写拼音 3:数字 4:汉字
 /// 
 public static string CreateCode(string codeType = "1|2|3|4")
 {
 var code = string.Empty;
 try
 {
 if (string.IsNullOrWhiteSpace(codeType) || codeType.IndexOf('|') < 0) { codeType = "1|2|3|4"; }
 var codeTypeArr = codeType.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
 var strLen = codeTypeArr.Length;
 //任务
 Task[] taskArr = new Task[strLen];
 for (int i = 0; i < strLen; i++)
 {
  var val = codeTypeArr[i];
  switch (val)
  {
  case "1": //小写拼音
  taskArr[i] = Task.Factory.StartNew(() => { return GetPinYinOrUpper(false); });
  break;
  case "2": //大写拼音
  taskArr[i] = Task.Factory.StartNew(() => { return GetPinYinOrUpper(); });
  break;
  case "3": //数字
  taskArr[i] = Task.Factory.StartNew(() => { return GetShuZi(); });
  break;
  case "4": //汉字
  taskArr[i] = Task.Factory.StartNew(() => { return GetHanZi(); });
  break;
  default:
  break;
  }
 }
 //等待完成 30s
 Task.WaitAll(taskArr, TimeSpan.FromSeconds(30));
 foreach (var item in taskArr)
 {
  code += item.Result;
 }
 }
 catch (Exception ex)
 {
 code = "我爱祖国";
 }
 return code;
 }

这里继续使用了关键字Task,来分发任务获取不同的验证码内容,个人认为最主要的还是通过参数设置 string codeType = "1|2|3|4" ,来确定验证码的组合方式,这样也达到了验证码格式的多样性;

» 把验证代码画到图片上

首先,咋们要明确的是要吧文字画在某个图片上,那么需要用到Graphics关键字,以此来创建画布把咋们的验证编码画到图片上,这里先上代码:

/// 
 /// 生成验证码图片流
 /// 
 /// 验证码文字
 /// 
 public static byte[] CreateValidateCodeStream(string code = "我爱祖国", int fontSize = 18, int width = 0, int height = 0, string fontFamily = "华文楷体")
 {
 var bb = new byte[0];
 //初始化画布
 var padding = 2;
 var len = code.Length;
 width = width <= 0 ? fontSize * 2 * (len - 1) + padding * 4 : width;
 height = height <= 0 ? fontSize * 2 : height;
 var image = new Bitmap(width, height);
 var g = Graphics.FromImage(image);
 try
 {
 var random = new Random();
 //清空背景色
 g.Clear(Color.White);
 //画横向中间干扰线
 var x1 = 0;
 var y1 = height / 2;
 var x2 = width;
 var y2 = y1;
 g.DrawLine(new Pen(Color.DarkRed), x1, y1, x2, y2);
 //字体
 var font = new Font(fontFamily, fontSize, (FontStyle.Bold | FontStyle.Italic));
 var brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height),
  Color.Blue, Color.DarkRed, 1f, true);
 //画文字
 var stringFomart = new StringFormat();
 //垂直居中
 stringFomart.LineAlignment = StringAlignment.Center;
 //水平居中
 stringFomart.Alignment = StringAlignment.Center;
 var rf = new Rectangle(Point.Empty, new Size(width, height));
 g.DrawString(code, font, brush, rf, stringFomart);
 //画图片的前景干扰点
 for (int i = 0; i < 100; i++)
 {
  var x = random.Next(image.Width);
  var y = random.Next(image.Height);
  image.SetPixel(x, y, Color.FromArgb(random.Next()));
 }
 //画图片的边框线
 g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1);
 //保存图片流
 var stream = new MemoryStream();
 image.Save(stream, ImageFormat.Jpeg);
 //输出图片流
 bb = stream.ToArray();
 }
 catch (Exception ex) { }
 finally
 {
 g.Dispose();
 image.Dispose();
 }
 return bb;
 }

这个列出画验证码图片方法的关键点:

1. 图片的高和宽度需要设置,这个根据不同页面布局方式而定,所以这里吧高和宽用作参数传递

2. 干扰线:通常验证码图片都以一两条干扰线,主要防止某些恶意用户使用图片识别软件进行不正规破解请求,我这里干扰线只设置了横向居中的一天直线代码如: g.DrawLine(new Pen(Color.DarkRed), x1, y1, x2, y2);

3. 字体:一个好看的字体通常也一种用户体验,因此这里根据需要参数传递字体;

4. 验证代码位于图片纵横向居中,这里的关键代码是:

思高数码广场
思高数码广场

修订记录:1.用户登陆增加了验证码,提高了安全性,登陆后不再显示登陆框。2.修改成了相对路径,不再一定需要放置在网站根目录下面。3.修改了类别搜索功能,并且可以暂时屏蔽,而不是删除,修改了先增加大类后出现无法修改中类名称的bug。4.增加了产品修改,可以保存修改。5.原来是借用别人的流量统计系统,不能统计某个页面的访问量,现采用的count.seecool.net的流量统计。6.帮助中心采用了fa

下载
 var stringFomart = new StringFormat();
 //垂直居中
 stringFomart.LineAlignment = StringAlignment.Center;
 //水平居中
 stringFomart.Alignment = StringAlignment.Center;

5.   g.DrawString(code, font, brush, rf, stringFomart); 主要用来把文字画到图片上,这是最关键的地方

6. 咋们通常都是吧验证码弄成图片流,而不是真的生成一个实体的验证码图片保存到服务器上,不然这样服务器很快就会磁盘不足,所以

 //保存图片流
 var stream = new MemoryStream();
 image.Save(stream, ImageFormat.Jpeg);
 //输出图片流
 bb = stream.ToArray();

这句的重要性也不可忽视,主要就把画的内容保存到流中方便使用

7. 最后千万不用忘了使用Dispose释放画布

» mvc登录操作测试验证码正确性

有了上面验证码生成类生成好的验证码图片,那么我们还需要测试验证下正确性和效果;下面我们使用mvc架构来做测试,先创建一个验证码测试Action并生成对应试图ValidCode.cshtml文件,然后自定义几个不同格式的验证码获取Action,代码如下:

public FileResult GetValidateCode()
 {
 //返回的验证码文字
 var code = string.Empty;
 var bb_code = ValidateCode.GetValidateCodeStream(ref code);

 return File(bb_code, "image/jpeg");
 }
 public FileResult GetValidateCode01()
 {
 var code = string.Empty;
 var bb_code = ValidateCode.GetValidateCodeStream(ref code, "1|2|3|4");
 return File(bb_code, "image/jpeg");
 }
 public FileResult GetValidateCode02()
 {
 var code = string.Empty;
 var bb_code = ValidateCode.GetValidateCodeStream(ref code, "4|3|2|1");
 return File(bb_code, "image/jpeg");
 }
 public FileResult GetValidateCode03()
 {
 var code = string.Empty;
 var bb_code = ValidateCode.GetValidateCodeStream(ref code, "2|2|2|2");
 return File(bb_code, "image/jpeg");
 }
 public FileResult GetValidateCode04()
 {
 var code = string.Empty;
 var bb_code = ValidateCode.GetValidateCodeStream(ref code, "4|4|4|4");
 return File(bb_code, "image/jpeg");
 }
 public FileResult GetValidateCode05()
 {
 var code = string.Empty;
 var bb_code = ValidateCode.GetValidateCodeStream(ref code, "1|1|1|1");
 return File(bb_code, "image/jpeg");
 }

感觉上几乎一模一样,只是对应的参数不一样,这里遵循的方法GetValidateCodeStream参数codeType格式是:为空表示自由组合  1:小写拼音 2:大写拼音 3:数字 4:汉字;然后我们往试图中填写如下代码:

神牛 - 验证码实例

全部随机 .net封装一个验证码生成类
小写|大写|数字|汉字 .net封装一个验证码生成类
汉字|数字|大写|小写 .net封装一个验证码生成类
全部大写 .net封装一个验证码生成类
全部汉字 .net封装一个验证码生成类
全部小写 .net封装一个验证码生成类

好了咋们生成下项目,看下效果图如下:

能从图中看到我们验证码格式的不同之处,这也是文章开头说的验证码格式的多样性,当然可能还有其他组成格式请允许我暂时忽略,下面我们来做一个点击图片获取新验证码的功能和点击登录按钮去后台程序判断验证码是否匹配的例子,先来修改试图界面代码如下:

@{
 ViewBag.Title = "ValidtCode";
}

神牛 - 验证码实例

全部随机 .net封装一个验证码生成类
小写|大写|数字|汉字 .net封装一个验证码生成类
汉字|数字|大写|小写 .net封装一个验证码生成类
全部大写 .net封装一个验证码生成类
全部汉字 .net封装一个验证码生成类
全部小写 .net封装一个验证码生成类

然后在Controller中增加如下登录验证代码:

public JsonResult UserLogin(string code)
 {
 var data = new Stage.Com.Extend.StageModel.MoData();
 if (string.IsNullOrWhiteSpace(code)) { data.Msg = "验证码不能为空"; return Json(data); }
 var compareCode = Session["code"];
 if (!compareCode.Equals(code)) { data.Msg = "验证码错误"; return Json(data); }
 data.IsOk = true;
 data.Msg = "验证码验证成功";
 return Json(data);
 }
 public FileResult GetValidateCode()
 {
 //返回的验证码文字
 var code = string.Empty;
 var bb_code = ValidateCode.GetValidateCodeStream(ref code);

 var key = "code";
 if (Session[key] != null)
 {
 Session.Remove(key);
 }
 Session[key] = code;
 return File(bb_code, "image/jpeg");
 }

由于我这里无法截动态图,所点击测试获取验证码我这里直接给出线上的一个例子,各位可以试试:http://lovexins.com:1001/home/ValidCode,点击获取新验证码的关键代码是:  $(this).attr("src", src); 重新给img元素的scr赋值,不过这里要注意由于浏览器缓存的原因,这里赋值的时候需要加上一个动态参数,我这里是使用时间作为请求参数,因此有了以下的代码: $(this).attr("src") + "?t=" + nowTime; 这是特别的地方需要注意;好了咋们来直接测试登陆是否能从后端判断验证码是否正确匹配吧,这里用的是session来保存获取验证码图片返回的验证代码,然后在登陆时候判断用户数据的验证码是否和后台session的验证一样:

验证失败:

验证成功:

好了测试用例就这么多,如果您觉得我这个验证码生成例子还可以并且您希望使用那么请注意,参数的传递,不同得到的验证码格式不同,主要方法是:

/// 
 /// 获取验证码图片流
 /// 
 /// 验证码个数(codeType设置 > codeLen设置)
 /// 为空表示自由组合 1:小写拼音 2:大写拼音 3:数字 4:汉字
 /// 
 public static byte[] GetValidateCodeStream(ref string code, string codeType = "", int codeLen = 0, int fontSize = 18, int width = 120, int height = 30)
 {
 //为空自由组合
 if (string.IsNullOrWhiteSpace(codeType))
 {
 for (int i = 0; i < codeLen; i++)
 {
  codeType += rm.Next(1, 5) + "|";
 }
 }
 code = CreateCode(codeType);
 return CreateValidateCodeStream(code, fontSize, width: width, height: height);
 }

【相关推荐】

1. ASP免费视频教程

2. ASP教程

3. 李炎恢ASP基础视频教程

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
AO3官网入口与中文阅读设置 AO3网页版使用与访问
AO3官网入口与中文阅读设置 AO3网页版使用与访问

本专题围绕 Archive of Our Own(AO3)官网入口展开,系统整理 AO3 最新可用官网地址、网页版访问方式、正确打开链接的方法,并详细讲解 AO3 中文界面设置、阅读语言切换及基础使用流程,帮助用户稳定访问 AO3 官网,高效完成中文阅读与作品浏览。

35

2026.02.02

主流快递单号查询入口 实时物流进度一站式追踪专题
主流快递单号查询入口 实时物流进度一站式追踪专题

本专题聚合极兔快递、京东快递、中通快递、圆通快递、韵达快递等主流物流平台的单号查询与运单追踪内容,重点解决单号查询、手机号查物流、官网入口直达、包裹进度实时追踪等高频问题,帮助用户快速获取最新物流状态,提升查件效率与使用体验。

7

2026.02.02

Golang WebAssembly(WASM)开发入门
Golang WebAssembly(WASM)开发入门

本专题系统讲解 Golang 在 WebAssembly(WASM)开发中的实践方法,涵盖 WASM 基础原理、Go 编译到 WASM 的流程、与 JavaScript 的交互方式、性能与体积优化,以及典型应用场景(如前端计算、跨平台模块)。帮助开发者掌握 Go 在新一代 Web 技术栈中的应用能力。

4

2026.02.02

PHP Swoole 高性能服务开发
PHP Swoole 高性能服务开发

本专题聚焦 PHP Swoole 扩展在高性能服务端开发中的应用,系统讲解协程模型、异步IO、TCP/HTTP/WebSocket服务器、进程与任务管理、常驻内存架构设计。通过实战案例,帮助开发者掌握 使用 PHP 构建高并发、低延迟服务端应用的工程化能力。

3

2026.02.02

Java JNI 与本地代码交互实战
Java JNI 与本地代码交互实战

本专题系统讲解 Java 通过 JNI 调用 C/C++ 本地代码的核心机制,涵盖 JNI 基本原理、数据类型映射、内存管理、异常处理、性能优化策略以及典型应用场景(如高性能计算、底层库封装)。通过实战示例,帮助开发者掌握 Java 与本地代码混合开发的完整流程。

2

2026.02.02

go语言 注释编码
go语言 注释编码

本专题整合了go语言注释、注释规范等等内容,阅读专题下面的文章了解更多详细内容。

62

2026.01.31

go语言 math包
go语言 math包

本专题整合了go语言math包相关内容,阅读专题下面的文章了解更多详细内容。

55

2026.01.31

go语言输入函数
go语言输入函数

本专题整合了go语言输入相关教程内容,阅读专题下面的文章了解更多详细内容。

27

2026.01.31

golang 循环遍历
golang 循环遍历

本专题整合了golang循环遍历相关教程,阅读专题下面的文章了解更多详细内容。

33

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
ASP.NET参考手册
ASP.NET参考手册

共0课时 | 0人学习

传播智客ASP.NET中级系列视频教程
传播智客ASP.NET中级系列视频教程

共33课时 | 6.4万人学习

传播智客ASP.NET高级系列视频教程
传播智客ASP.NET高级系列视频教程

共34课时 | 6.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号