一个验证码对于一个网站的作用不言而喻,而随着技术的发展验证码的种类也开始多了起来,发展至今很多网站已经不再使用一种验证码,为满足需求程序猿就要写很多的方法来适应需求,今天我就来介绍我之前收集到的验证码的方法写成的一个帮助类,来解决我们日常开发当中的验证码需求问题。

  帮助类中验证码是以byte[]的格式返回的,方便使用。

  英文字符验证码

  

  1. /// <summary>
  2. /// 英文字符验证码
  3. /// </summary>
  4. /// <param name="Code">传出验证码</param>
  5. /// <param name="CodeLength">验证码字符</param>
  6. /// <returns></returns>
  7. public static byte[] GraphCode(out string Code,int CodeLength)
  8. {
  9. int Width = ;//默认为100
  10. int Height = ;//默认为40
  11. int FontSize = ;//默认为20
  12. byte[] bytes = GraphCode(out Code, CodeLength, Width, Height, FontSize);
  13. return bytes;
  14. }
  15.  
  16. /// <summary>
  17. /// 产生图形验证码。
  18. /// </summary>
  19. /// <param name="Code">传出验证码。</param>
  20. /// <param name="CodeLength">验证码字符。</param>
  21. /// <param name="Width"></param>
  22. /// <param name="Height"></param>
  23. /// <param name="FontSize"></param>
  24. /// <returns></returns>
  25. public static byte[] GraphCode(out string Code, int CodeLength, int Width, int Height, int FontSize)
  26. {
  27. string code = string.Empty;
  28. String sCode = String.Empty;
  29. //顏色列表,用于验证码、噪线、噪点
  30. Color[] oColors ={
  31. Color.Black,
  32. Color.Red,
  33. Color.Blue,
  34. Color.Green,
  35. Color.Orange,
  36. Color.Brown,
  37. Color.Brown,
  38. Color.DarkBlue
  39. };
  40. //字体列表,用于验证码
  41. string[] oFontNames = { "Times New Roman", "MS Mincho", "Book Antiqua", "Gungsuh", "PMingLiU", "Impact" };
  42. //验证码的字元集
  43. char[] oCharacter =
  44. {
  45. 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
  46. 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'
  47. };
  48. Random oRnd = new Random();
  49. Bitmap oBmp = null;
  50. Graphics oGraphics = null;
  51. int N1 = ;
  52. //生成验证码字串
  53. for (N1 = ; N1 <= CodeLength - ; N1++)
  54. {
  55. sCode += oCharacter[oRnd.Next(oCharacter.Length)];
  56. }
  57. oBmp = new Bitmap(Width, Height);
  58. oGraphics = Graphics.FromImage(oBmp);
  59. oGraphics.Clear(Color.White);
  60. try
  61. {
  62. oGraphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
  63. Font f = new System.Drawing.Font("宋体", FontSize, (System.Drawing.FontStyle.Bold));
  64. // 前景色
  65. Brush b = new System.Drawing.SolidBrush(Color.Black);
  66. // 背景色
  67. oGraphics.Clear(Color.White);
  68. // 填充文字
  69. for (int i = ; i < sCode.Length; i++)
  70. {
  71. oGraphics.DrawString(sCode[i].ToString(), f, b, new Rectangle(i * (FontSize - ), , (FontSize - ), Height));
  72. }
  73. // 随机线条
  74. Pen linePen = new Pen(Color.Gray, );
  75. Random rand = new Random();
  76. for (int i = ; i < ; i++)
  77. {
  78. int x1 = rand.Next(oBmp.Width);
  79. int y1 = rand.Next(oBmp.Height);
  80. int x2 = rand.Next(oBmp.Width);
  81. int y2 = rand.Next(oBmp.Height);
  82. oGraphics.DrawLine(linePen, x1, y1, x2, y2);
  83. }
  84.  
  85. // 随机点
  86. for (int i = ; i < ; i++)
  87. {
  88. int x = rand.Next(oBmp.Width);
  89. int y = rand.Next(oBmp.Height);
  90. oBmp.SetPixel(x, y, Color.FromArgb(rand.Next(), rand.Next(), rand.Next()));
  91. }
  92.  
  93. Code = sCode;
  94. //保存图片数据
  95. MemoryStream stream = new MemoryStream();
  96. oBmp.Save(stream, ImageFormat.Jpeg);
  97. //输出图片流
  98. return stream.ToArray();
  99. }
  100. finally
  101. {
  102. oGraphics.Dispose();
  103. }
  104. }

验证码中的字元集是可以改变的,可以去掉一些容易混淆的字元,我这里使用了全部的字元

  数字字符验证码

  1. /// <summary>
  2. /// 纯数字图形验证码
  3. /// </summary>
  4. /// <param name="Code">传出验证码</param>
  5. /// <param name="CodeLength">验证码字符</param>
  6. /// <returns></returns>
  7. public static byte[] NumCode(out string Code, int CodeLength)
  8. {
  9. Code = CreateValidateCode(CodeLength);
  10. byte[] bytes = CreateValidateGraphic(Code);
  11. return bytes;
  12. }
  13. /// <summary>
  14. /// 生成验证码
  15. /// </summary>
  16. /// <param name="CodeLength">指定验证码的长度</param>
  17. /// <returns></returns>
  18. private static string CreateValidateCode(int CodeLength)
  19. {
  20. int[] randMembers = new int[CodeLength];
  21. int[] validateNums = new int[CodeLength];
  22. string validateNumberStr = "";
  23. //生成起始序列值
  24. int seekSeek = unchecked((int)DateTime.Now.Ticks);
  25. Random seekRand = new Random(seekSeek);
  26. int beginSeek = (int)seekRand.Next(, Int32.MaxValue - CodeLength * );
  27. int[] seeks = new int[CodeLength];
  28. for (int i = ; i < CodeLength; i++)
  29. {
  30. beginSeek += ;
  31. seeks[i] = beginSeek;
  32. }
  33. //生成随机数字
  34. for (int i = ; i < CodeLength; i++)
  35. {
  36. Random rand = new Random(seeks[i]);
  37. int pownum = * (int)Math.Pow(, CodeLength);
  38. randMembers[i] = rand.Next(pownum, Int32.MaxValue);
  39. }
  40. //抽取随机数字
  41. for (int i = ; i < CodeLength; i++)
  42. {
  43. string numStr = randMembers[i].ToString();
  44. int numCodeLength = numStr.Length;
  45. Random rand = new Random();
  46. int numPosition = rand.Next(, numCodeLength - );
  47. validateNums[i] = Int32.Parse(numStr.Substring(numPosition, ));
  48. }
  49. //生成验证码
  50. for (int i = ; i < CodeLength; i++)
  51. {
  52. validateNumberStr += validateNums[i].ToString();
  53. }
  54. return validateNumberStr;
  55. }
  56.  
  57. /// <summary>
  58. /// 创建验证码的图片
  59. /// </summary>
  60. /// <param name="validateCode">验证码</param>
  61. private static byte[] CreateValidateGraphic(string validateCode)
  62. {
  63. Bitmap image = new Bitmap((int)Math.Ceiling(validateCode.Length * 12.0), );
  64. Graphics g = Graphics.FromImage(image);
  65. try
  66. {
  67. //生成随机生成器
  68. Random random = new Random();
  69. //清空图片背景色
  70. g.Clear(Color.White);
  71. //画图片的干扰线
  72. for (int i = ; i < ; i++)
  73. {
  74. int x1 = random.Next(image.Width);
  75. int x2 = random.Next(image.Width);
  76. int y1 = random.Next(image.Height);
  77. int y2 = random.Next(image.Height);
  78. g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2);
  79. }
  80. Font font = new Font("Arial", , (FontStyle.Bold | FontStyle.Italic));
  81. LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(, , image.Width, image.Height),
  82. Color.Blue, Color.DarkRed, 1.2f, true);
  83. g.DrawString(validateCode, font, brush, , );
  84. //画图片的前景干扰点
  85. for (int i = ; i < ; i++)
  86. {
  87. int x = random.Next(image.Width);
  88. int y = random.Next(image.Height);
  89. image.SetPixel(x, y, Color.FromArgb(random.Next()));
  90. }
  91. //画图片的边框线
  92. g.DrawRectangle(new Pen(Color.Silver), , , image.Width - , image.Height - );
  93. //保存图片数据
  94. MemoryStream stream = new MemoryStream();
  95. image.Save(stream, ImageFormat.Jpeg);
  96. //输出图片流
  97. return stream.ToArray();
  98. }
  99. finally
  100. {
  101. g.Dispose();
  102. image.Dispose();
  103. }
  104. }

数字与字符混合验证码

  1. /// <summary>
  2. /// 生成随机字符串
  3. /// </summary>
  4. /// <param name="NumCount"></param>
  5. /// <returns></returns>
  6. private static string CreateRandomNum(int NumCount)
  7. {
  8. char[] allCharArray =
  9. {
  10. '','','','','','','','','',
  11. 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
  12. 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'
  13. };
  14. string randomNum = "";
  15. int temp = -;//记录上次随机数的数值,尽量避免产生几个相同的随机数
  16. Random rand = new Random();
  17. for (int i = ; i < NumCount; i++)
  18. {
  19. if (temp != -)
  20. {
  21. rand = new Random(i * temp * ((int)DateTime.Now.Ticks));
  22. }
  23. int t = rand.Next();
  24. if (temp == t)
  25. {
  26. return CreateRandomNum(NumCount);
  27. }
  28. temp = t;
  29. randomNum += allCharArray[t];
  30. }
  31. return randomNum;
  32. }
  33.  
  34. /// <summary>
  35. /// 数字和字符混合验证码
  36. /// </summary>
  37. /// <param name="Code">传出字符</param>
  38. /// <param name="NumCount">字节长度</param>
  39. /// <param name="Width">图片宽度</param>
  40. /// <param name="Height">图片长度</param>
  41. /// <param name="FontSize">文字大小</param>
  42. /// <returns></returns>
  43. public static byte[] GNCode(out string Code, int NumCount, int Width, int Height, int FontSize)
  44. {
  45. string validateNum = CreateRandomNum(NumCount);
  46. Code = null;
  47. if (validateNum == null || validateNum.Trim() == String.Empty)
  48. return null;
  49. //生成Bitmap图像
  50. System.Drawing.Bitmap image = new System.Drawing.Bitmap(Width, Height);
  51. Graphics g = Graphics.FromImage(image);
  52.  
  53. try
  54. {
  55. //生成随机生成器
  56. Random random = new Random();
  57.  
  58. //清空图片背景色
  59. g.Clear(Color.White);
  60.  
  61. g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
  62. Font f = new System.Drawing.Font("宋体", FontSize, (System.Drawing.FontStyle.Bold));
  63. // 前景色
  64. Brush b = new System.Drawing.SolidBrush(Color.Black);
  65. // 背景色
  66. g.Clear(Color.White);
  67. // 填充文字
  68. for (int i = ; i < validateNum.Length; i++)
  69. {
  70. g.DrawString(validateNum[i].ToString(), f, b, new Rectangle(i * (FontSize - ), , (FontSize - ), Height));
  71. }
  72. // 随机线条
  73. Pen linePen = new Pen(Color.Gray, );
  74. Random rand = new Random();
  75. for (int i = ; i < ; i++)
  76. {
  77. int x1 = rand.Next(image.Width);
  78. int y1 = rand.Next(image.Height);
  79. int x2 = rand.Next(image.Width);
  80. int y2 = rand.Next(image.Height);
  81. g.DrawLine(linePen, x1, y1, x2, y2);
  82. }
  83.  
  84. // 随机点
  85. for (int i = ; i < ; i++)
  86. {
  87. int x = rand.Next(image.Width);
  88. int y = rand.Next(image.Height);
  89. image.SetPixel(x, y, Color.FromArgb(rand.Next(), rand.Next(), rand.Next()));
  90. }
  91.  
  92. Code = validateNum;
  93.  
  94. //保存图片数据
  95. MemoryStream stream = new MemoryStream();
  96. image.Save(stream, ImageFormat.Jpeg);
  97. //输出图片流
  98. return stream.ToArray();
  99. }
  100. finally
  101. {
  102. g.Dispose();
  103. image.Dispose();
  104. }
  105. }

数学算式验证码

  1. /// <summary>
  2. /// 数学算式的验证码
  3. /// </summary>
  4. /// <param name="Code"></param>
  5. /// <returns></returns>
  6. public static byte[] MathVerifyCode(out int Code)
  7. {
  8. int mathResult = ;
  9. string expression = null;
  10.  
  11. Random rnd = new Random();
  12.  
  13. ////生成3个10以内的整数,用来运算
  14. int operator1 = rnd.Next(, );
  15. int operator2 = rnd.Next(, );
  16. int operator3 = rnd.Next(, );
  17.  
  18. ////随机组合运算顺序,只做 + 和 - 运算
  19. switch (rnd.Next(, ))
  20. {
  21. case :
  22. mathResult = operator1 + operator2 + operator3;
  23. expression = string.Format("{0} + {1} + {2} = ?", operator1, operator2, operator3);
  24. break;
  25. case :
  26. mathResult = operator2 - operator1 + operator3;
  27. expression = string.Format("{0} - {1} + {2} = ?", operator2, operator1, operator3);
  28. break;
  29. default:
  30. mathResult = operator2 + operator1 - operator3;
  31. expression = string.Format("{0} + {1} - {2} = ?", operator2, operator1, operator3);
  32. break;
  33. }
  34. Code = mathResult;
  35. using (Bitmap bmp = new Bitmap(, ))
  36. {
  37. using (Graphics graph = Graphics.FromImage(bmp))
  38. {
  39. graph.Clear(Color.FromArgb(, , )); ////背景色,可自行设置
  40.  
  41. ////画噪点
  42. for (int i = ; i <= ; i++)
  43. {
  44. graph.DrawRectangle(
  45. new Pen(Color.FromArgb(rnd.Next(, ), rnd.Next(, ), rnd.Next(, ))),
  46. rnd.Next(, ),
  47. rnd.Next(, ),
  48. ,
  49. );
  50. }
  51.  
  52. ////输出表达式
  53. for (int i = ; i < expression.Length; i++)
  54. {
  55. graph.DrawString(expression.Substring(i, ),
  56. new Font(FontFamily.GenericSansSerif, , FontStyle.Bold),
  57. new SolidBrush(Color.FromArgb(rnd.Next(), rnd.Next(), rnd.Next())),
  58. + i * ,
  59. rnd.Next(, ));
  60. }
  61.  
  62. ////画边框,不需要可以注释掉
  63. graph.DrawRectangle(new Pen(Color.Firebrick), , , - , - );
  64. }
  65.  
  66. MemoryStream stream = new MemoryStream();
  67. bmp.Save(stream, ImageFormat.Jpeg);
  68. //输出图片流
  69. return stream.ToArray();
  70. }
  71. }

数学算式验证码里面的算式结构是可以改成更复杂的,不过个人觉得加减法已经可以满足日常需求

使用方式

以ASP.NET MVC为例,使用方式很简单,写一个方法,以图片文件的形式输出

  1. /// <summary>
  2. /// 验证码
  3. /// </summary>
  4. /// <returns></returns>
  5. public virtual ActionResult VerifyImage()
  6. {
  7. string Code = "";
  8. byte[] bytes = CodeHelper.GNCode(out Code, , , , );
  9. Session["Code"] = Code;
  10. return File(bytes, @"image/jpeg");
  11. }

这里的CodeHelper就是我们写好的验证码帮助类,直接调用

前端放一张图片来显示验证码

  1. <img src="@Url.Action("VerifyImage")" id="VerifyImage" title="点击换一个">

应用截图

构建一个.net的干货类库,以便于快速的开发 - 验证码的更多相关文章

  1. 构建一个.net的干货类库,以便于快速的开发 - 前言

    前言: 工作已经快两年了,项目也做过不少,不知道大家有没有一个习惯,就是把在做项目过程中那些好的方法记录下来.我觉得这个习惯在开发的过程中还是很有用的,举个例子,我之前做过一个支付宝的支付功能,然后把 ...

  2. 构建一个.net的干货类库,以便于快速的开发 - 加密

    在开发程序的时候,加密是一个程序一个必须的功能,基本上任何程序都会用到加密,而不同的加密方式又适应不同需求,有些加密是不可逆的,最常见是用于用户密码的加密,因为很多时候程序里面不该显示出用户的明文密码 ...

  3. 构建一个.net的干货类库,以便于快速的开发 - 工具类

    相信每一个开发的框架都会有一个工具类,工具类的作用有很多,通常我会将最常用的方法放在工具类里 取得用户IP 取得网站根目录的物理路径 枚举相关 非法关键字检查 绝对路径改为相对路径 获取小数位(四舍五 ...

  4. 简单使用Laravel-admin构建一个功能强大的后台管理

    Laravel-admin可以快速构建一个功能强大的后台,方便快速开发. 以下内容记录简单使用Laravel-admin,以及遇到小错误的解决方法. Laravel-admin 依赖以下环境 需要提前 ...

  5. 【云开发】10分钟零基础学会做一个快递查询微信小程序,快速掌握微信小程序开发技能(轮播图、API请求)

    大家好,我叫小秃僧 这次分享的是10分钟零基础学会做一个快递查询微信小程序,快速掌握开发微信小程序技能. 这篇文章偏基础,特别适合还没有开发过微信小程序的童鞋,一些概念和逻辑我会讲细一点,尽可能用图说 ...

  6. 利用 vue-cli 构建一个 Vue 项目

    一.项目初始构建 现在如果要构建一个 Vue 的项目,最方便的方式,莫过于使用官方的 vue-cli . 首先,咱们先来全局安装 vue-cli ,打开命令行工具,输入以下命令: $ npm inst ...

  7. 构建一个基本的前端自动化开发环境 —— 基于 Gulp 的前端集成解决方案(四)

    通过前面几节的准备工作,对于 npm / node / gulp 应该已经有了基本的认识,本节主要介绍如何构建一个基本的前端自动化开发环境. 下面将逐步构建一个可以自动编译 sass 文件.压缩 ja ...

  8. .Net中的AOP系列之构建一个汽车租赁应用

    返回<.Net中的AOP>系列学习总目录 本篇目录 开始一个新项目 没有AOP的生活 变更的代价 使用AOP重构 本系列的源码本人已托管于Coding上:点击查看. 本系列的实验环境:VS ...

  9. 基于Vue2.0+Vue-router构建一个简单的单页应用

    爱编程爱分享,原创文章,转载请注明出处,谢谢!http://www.cnblogs.com/fozero/p/6185492.html 一.介绍 vue.js 是 目前 最火的前端框架,vue.js ...

随机推荐

  1. 在开发过程中,如何在手机上测试vue-cli构建的项目

    由于有时候谷歌手机调试与真是的手机环境还是有一定的差距,所以需要在手机上测试项目. 手机上测试vue-cli构建项目方法: 打开项目config/index.js文件,找到module.exports ...

  2. 推荐系统(1)--splitting approaches for context-aware recommendation

    开篇语: 大一的时候.在实验室老师和师兄的带领下.我開始接触推荐系统.时光匆匆,转眼已是大三,因为大三课甚是少.于是便有了时间将自己所学的东西做下总结. 第一篇博客.献给过去三年里带我飞的老师和师兄们 ...

  3. Servlet的引入

    一.分析 此模式有问题: 1.jsp需要呼叫javabean StudentService stuService = new StudentServiceImpl(); List<Student ...

  4. [办公应用]如何在WORD中让英文网址可以在字符中间换行

    有时候我们写文章,存在中英文混合录入的情况.一般情况下,office 2003的word软件中,会自作聪明的避免单词断行显示,也就是说它会默认尽量把一个单词显示在某一行内,从而避免单词被分开.但有时候 ...

  5. 下面forward和redirect的描述,正确的是(ABCD)

    A:forward是服务器将控制权转交给内部服务器对象,由新的对象来全权负责响应用户的请求 B:执行forward时,浏览器不知道服务器所发送的内容从那里来,浏览器地址栏中还是原来的地址 C:执行re ...

  6. reverse proxy and forward proxy

    1 什么是forward proxy 一句话,client的proxy就是forward proxy. 2 什么是reverse proxy 一句话,server的proxy就是reverse pro ...

  7. Oracle - 查询语句 - 分组函数

    /* 分组函数 不能再select子句中出现普通的列,除非这个列在group by中给出 所有的空值都会被分为一组 分组过滤 SELECT FROM WHERE GROUPBY HAVING ORDE ...

  8. android 自定义View开发实战(六) 可拖动的GridView

    1前言 由于项目需求,需要把项目的主界面采用GridView显示,并且需要根据模块优先级支持拖动图标(砍死产品狗).为此,自定义了一个支持拖拽图标的GridView.效果如下: 具体效果如上图 2 可 ...

  9. 深入探析c# Socket

    最近浏览了几篇有关Socket发送消息的文章,发现大家对Socket Send方法理解有所偏差,现将自己在开发过程中对Socket的领悟写出来,以供大家参考. (一)架构 基于TCP协议的Socket ...

  10. JavaScript-Tool:CKFinder

    ylbtech-JavaScript-Tool:CKFinder 1.返回顶部 CKFinder是一个强大而易于使用的Web浏览器的Ajax文件管理器. 其简单的界面使得它直观,快速学习的各类用户,从 ...