构建一个.net的干货类库,以便于快速的开发 - 验证码
一个验证码对于一个网站的作用不言而喻,而随着技术的发展验证码的种类也开始多了起来,发展至今很多网站已经不再使用一种验证码,为满足需求程序猿就要写很多的方法来适应需求,今天我就来介绍我之前收集到的验证码的方法写成的一个帮助类,来解决我们日常开发当中的验证码需求问题。
帮助类中验证码是以byte[]的格式返回的,方便使用。
英文字符验证码
/// <summary>
/// 英文字符验证码
/// </summary>
/// <param name="Code">传出验证码</param>
/// <param name="CodeLength">验证码字符</param>
/// <returns></returns>
public static byte[] GraphCode(out string Code,int CodeLength)
{
int Width = ;//默认为100
int Height = ;//默认为40
int FontSize = ;//默认为20
byte[] bytes = GraphCode(out Code, CodeLength, Width, Height, FontSize);
return bytes;
} /// <summary>
/// 产生图形验证码。
/// </summary>
/// <param name="Code">传出验证码。</param>
/// <param name="CodeLength">验证码字符。</param>
/// <param name="Width"></param>
/// <param name="Height"></param>
/// <param name="FontSize"></param>
/// <returns></returns>
public static byte[] GraphCode(out string Code, int CodeLength, int Width, int Height, int FontSize)
{
string code = string.Empty;
String sCode = String.Empty;
//顏色列表,用于验证码、噪线、噪点
Color[] oColors ={
Color.Black,
Color.Red,
Color.Blue,
Color.Green,
Color.Orange,
Color.Brown,
Color.Brown,
Color.DarkBlue
};
//字体列表,用于验证码
string[] oFontNames = { "Times New Roman", "MS Mincho", "Book Antiqua", "Gungsuh", "PMingLiU", "Impact" };
//验证码的字元集
char[] oCharacter =
{
'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',
'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'
};
Random oRnd = new Random();
Bitmap oBmp = null;
Graphics oGraphics = null;
int N1 = ;
//生成验证码字串
for (N1 = ; N1 <= CodeLength - ; N1++)
{
sCode += oCharacter[oRnd.Next(oCharacter.Length)];
}
oBmp = new Bitmap(Width, Height);
oGraphics = Graphics.FromImage(oBmp);
oGraphics.Clear(Color.White);
try
{
oGraphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
Font f = new System.Drawing.Font("宋体", FontSize, (System.Drawing.FontStyle.Bold));
// 前景色
Brush b = new System.Drawing.SolidBrush(Color.Black);
// 背景色
oGraphics.Clear(Color.White);
// 填充文字
for (int i = ; i < sCode.Length; i++)
{
oGraphics.DrawString(sCode[i].ToString(), f, b, new Rectangle(i * (FontSize - ), , (FontSize - ), Height));
}
// 随机线条
Pen linePen = new Pen(Color.Gray, );
Random rand = new Random();
for (int i = ; i < ; i++)
{
int x1 = rand.Next(oBmp.Width);
int y1 = rand.Next(oBmp.Height);
int x2 = rand.Next(oBmp.Width);
int y2 = rand.Next(oBmp.Height);
oGraphics.DrawLine(linePen, x1, y1, x2, y2);
} // 随机点
for (int i = ; i < ; i++)
{
int x = rand.Next(oBmp.Width);
int y = rand.Next(oBmp.Height);
oBmp.SetPixel(x, y, Color.FromArgb(rand.Next(), rand.Next(), rand.Next()));
} Code = sCode;
//保存图片数据
MemoryStream stream = new MemoryStream();
oBmp.Save(stream, ImageFormat.Jpeg);
//输出图片流
return stream.ToArray();
}
finally
{
oGraphics.Dispose();
}
}
验证码中的字元集是可以改变的,可以去掉一些容易混淆的字元,我这里使用了全部的字元
数字字符验证码
/// <summary>
/// 纯数字图形验证码
/// </summary>
/// <param name="Code">传出验证码</param>
/// <param name="CodeLength">验证码字符</param>
/// <returns></returns>
public static byte[] NumCode(out string Code, int CodeLength)
{
Code = CreateValidateCode(CodeLength);
byte[] bytes = CreateValidateGraphic(Code);
return bytes;
}
/// <summary>
/// 生成验证码
/// </summary>
/// <param name="CodeLength">指定验证码的长度</param>
/// <returns></returns>
private static string CreateValidateCode(int CodeLength)
{
int[] randMembers = new int[CodeLength];
int[] validateNums = new int[CodeLength];
string validateNumberStr = "";
//生成起始序列值
int seekSeek = unchecked((int)DateTime.Now.Ticks);
Random seekRand = new Random(seekSeek);
int beginSeek = (int)seekRand.Next(, Int32.MaxValue - CodeLength * );
int[] seeks = new int[CodeLength];
for (int i = ; i < CodeLength; i++)
{
beginSeek += ;
seeks[i] = beginSeek;
}
//生成随机数字
for (int i = ; i < CodeLength; i++)
{
Random rand = new Random(seeks[i]);
int pownum = * (int)Math.Pow(, CodeLength);
randMembers[i] = rand.Next(pownum, Int32.MaxValue);
}
//抽取随机数字
for (int i = ; i < CodeLength; i++)
{
string numStr = randMembers[i].ToString();
int numCodeLength = numStr.Length;
Random rand = new Random();
int numPosition = rand.Next(, numCodeLength - );
validateNums[i] = Int32.Parse(numStr.Substring(numPosition, ));
}
//生成验证码
for (int i = ; i < CodeLength; i++)
{
validateNumberStr += validateNums[i].ToString();
}
return validateNumberStr;
} /// <summary>
/// 创建验证码的图片
/// </summary>
/// <param name="validateCode">验证码</param>
private static byte[] CreateValidateGraphic(string validateCode)
{
Bitmap image = new Bitmap((int)Math.Ceiling(validateCode.Length * 12.0), );
Graphics g = Graphics.FromImage(image);
try
{
//生成随机生成器
Random random = new Random();
//清空图片背景色
g.Clear(Color.White);
//画图片的干扰线
for (int i = ; i < ; i++)
{
int x1 = random.Next(image.Width);
int x2 = random.Next(image.Width);
int y1 = random.Next(image.Height);
int y2 = random.Next(image.Height);
g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2);
}
Font font = new Font("Arial", , (FontStyle.Bold | FontStyle.Italic));
LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(, , image.Width, image.Height),
Color.Blue, Color.DarkRed, 1.2f, true);
g.DrawString(validateCode, font, brush, , );
//画图片的前景干扰点
for (int i = ; i < ; i++)
{
int x = random.Next(image.Width);
int y = random.Next(image.Height);
image.SetPixel(x, y, Color.FromArgb(random.Next()));
}
//画图片的边框线
g.DrawRectangle(new Pen(Color.Silver), , , image.Width - , image.Height - );
//保存图片数据
MemoryStream stream = new MemoryStream();
image.Save(stream, ImageFormat.Jpeg);
//输出图片流
return stream.ToArray();
}
finally
{
g.Dispose();
image.Dispose();
}
}
数字与字符混合验证码
/// <summary>
/// 生成随机字符串
/// </summary>
/// <param name="NumCount"></param>
/// <returns></returns>
private static string CreateRandomNum(int NumCount)
{
char[] allCharArray =
{
'','','','','','','','','',
'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',
'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'
};
string randomNum = "";
int temp = -;//记录上次随机数的数值,尽量避免产生几个相同的随机数
Random rand = new Random();
for (int i = ; i < NumCount; i++)
{
if (temp != -)
{
rand = new Random(i * temp * ((int)DateTime.Now.Ticks));
}
int t = rand.Next();
if (temp == t)
{
return CreateRandomNum(NumCount);
}
temp = t;
randomNum += allCharArray[t];
}
return randomNum;
} /// <summary>
/// 数字和字符混合验证码
/// </summary>
/// <param name="Code">传出字符</param>
/// <param name="NumCount">字节长度</param>
/// <param name="Width">图片宽度</param>
/// <param name="Height">图片长度</param>
/// <param name="FontSize">文字大小</param>
/// <returns></returns>
public static byte[] GNCode(out string Code, int NumCount, int Width, int Height, int FontSize)
{
string validateNum = CreateRandomNum(NumCount);
Code = null;
if (validateNum == null || validateNum.Trim() == String.Empty)
return null;
//生成Bitmap图像
System.Drawing.Bitmap image = new System.Drawing.Bitmap(Width, Height);
Graphics g = Graphics.FromImage(image); try
{
//生成随机生成器
Random random = new Random(); //清空图片背景色
g.Clear(Color.White); g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
Font f = new System.Drawing.Font("宋体", FontSize, (System.Drawing.FontStyle.Bold));
// 前景色
Brush b = new System.Drawing.SolidBrush(Color.Black);
// 背景色
g.Clear(Color.White);
// 填充文字
for (int i = ; i < validateNum.Length; i++)
{
g.DrawString(validateNum[i].ToString(), f, b, new Rectangle(i * (FontSize - ), , (FontSize - ), Height));
}
// 随机线条
Pen linePen = new Pen(Color.Gray, );
Random rand = new Random();
for (int i = ; i < ; i++)
{
int x1 = rand.Next(image.Width);
int y1 = rand.Next(image.Height);
int x2 = rand.Next(image.Width);
int y2 = rand.Next(image.Height);
g.DrawLine(linePen, x1, y1, x2, y2);
} // 随机点
for (int i = ; i < ; i++)
{
int x = rand.Next(image.Width);
int y = rand.Next(image.Height);
image.SetPixel(x, y, Color.FromArgb(rand.Next(), rand.Next(), rand.Next()));
} Code = validateNum; //保存图片数据
MemoryStream stream = new MemoryStream();
image.Save(stream, ImageFormat.Jpeg);
//输出图片流
return stream.ToArray();
}
finally
{
g.Dispose();
image.Dispose();
}
}
数学算式验证码
/// <summary>
/// 数学算式的验证码
/// </summary>
/// <param name="Code"></param>
/// <returns></returns>
public static byte[] MathVerifyCode(out int Code)
{
int mathResult = ;
string expression = null; Random rnd = new Random(); ////生成3个10以内的整数,用来运算
int operator1 = rnd.Next(, );
int operator2 = rnd.Next(, );
int operator3 = rnd.Next(, ); ////随机组合运算顺序,只做 + 和 - 运算
switch (rnd.Next(, ))
{
case :
mathResult = operator1 + operator2 + operator3;
expression = string.Format("{0} + {1} + {2} = ?", operator1, operator2, operator3);
break;
case :
mathResult = operator2 - operator1 + operator3;
expression = string.Format("{0} - {1} + {2} = ?", operator2, operator1, operator3);
break;
default:
mathResult = operator2 + operator1 - operator3;
expression = string.Format("{0} + {1} - {2} = ?", operator2, operator1, operator3);
break;
}
Code = mathResult;
using (Bitmap bmp = new Bitmap(, ))
{
using (Graphics graph = Graphics.FromImage(bmp))
{
graph.Clear(Color.FromArgb(, , )); ////背景色,可自行设置 ////画噪点
for (int i = ; i <= ; i++)
{
graph.DrawRectangle(
new Pen(Color.FromArgb(rnd.Next(, ), rnd.Next(, ), rnd.Next(, ))),
rnd.Next(, ),
rnd.Next(, ),
,
);
} ////输出表达式
for (int i = ; i < expression.Length; i++)
{
graph.DrawString(expression.Substring(i, ),
new Font(FontFamily.GenericSansSerif, , FontStyle.Bold),
new SolidBrush(Color.FromArgb(rnd.Next(), rnd.Next(), rnd.Next())),
+ i * ,
rnd.Next(, ));
} ////画边框,不需要可以注释掉
graph.DrawRectangle(new Pen(Color.Firebrick), , , - , - );
} MemoryStream stream = new MemoryStream();
bmp.Save(stream, ImageFormat.Jpeg);
//输出图片流
return stream.ToArray();
}
}
数学算式验证码里面的算式结构是可以改成更复杂的,不过个人觉得加减法已经可以满足日常需求
使用方式
以ASP.NET MVC为例,使用方式很简单,写一个方法,以图片文件的形式输出
/// <summary>
/// 验证码
/// </summary>
/// <returns></returns>
public virtual ActionResult VerifyImage()
{
string Code = "";
byte[] bytes = CodeHelper.GNCode(out Code, , , , );
Session["Code"] = Code;
return File(bytes, @"image/jpeg");
}
这里的CodeHelper就是我们写好的验证码帮助类,直接调用
前端放一张图片来显示验证码
<img src="@Url.Action("VerifyImage")" id="VerifyImage" title="点击换一个">
应用截图
构建一个.net的干货类库,以便于快速的开发 - 验证码的更多相关文章
- 构建一个.net的干货类库,以便于快速的开发 - 前言
前言: 工作已经快两年了,项目也做过不少,不知道大家有没有一个习惯,就是把在做项目过程中那些好的方法记录下来.我觉得这个习惯在开发的过程中还是很有用的,举个例子,我之前做过一个支付宝的支付功能,然后把 ...
- 构建一个.net的干货类库,以便于快速的开发 - 加密
在开发程序的时候,加密是一个程序一个必须的功能,基本上任何程序都会用到加密,而不同的加密方式又适应不同需求,有些加密是不可逆的,最常见是用于用户密码的加密,因为很多时候程序里面不该显示出用户的明文密码 ...
- 构建一个.net的干货类库,以便于快速的开发 - 工具类
相信每一个开发的框架都会有一个工具类,工具类的作用有很多,通常我会将最常用的方法放在工具类里 取得用户IP 取得网站根目录的物理路径 枚举相关 非法关键字检查 绝对路径改为相对路径 获取小数位(四舍五 ...
- 简单使用Laravel-admin构建一个功能强大的后台管理
Laravel-admin可以快速构建一个功能强大的后台,方便快速开发. 以下内容记录简单使用Laravel-admin,以及遇到小错误的解决方法. Laravel-admin 依赖以下环境 需要提前 ...
- 【云开发】10分钟零基础学会做一个快递查询微信小程序,快速掌握微信小程序开发技能(轮播图、API请求)
大家好,我叫小秃僧 这次分享的是10分钟零基础学会做一个快递查询微信小程序,快速掌握开发微信小程序技能. 这篇文章偏基础,特别适合还没有开发过微信小程序的童鞋,一些概念和逻辑我会讲细一点,尽可能用图说 ...
- 利用 vue-cli 构建一个 Vue 项目
一.项目初始构建 现在如果要构建一个 Vue 的项目,最方便的方式,莫过于使用官方的 vue-cli . 首先,咱们先来全局安装 vue-cli ,打开命令行工具,输入以下命令: $ npm inst ...
- 构建一个基本的前端自动化开发环境 —— 基于 Gulp 的前端集成解决方案(四)
通过前面几节的准备工作,对于 npm / node / gulp 应该已经有了基本的认识,本节主要介绍如何构建一个基本的前端自动化开发环境. 下面将逐步构建一个可以自动编译 sass 文件.压缩 ja ...
- .Net中的AOP系列之构建一个汽车租赁应用
返回<.Net中的AOP>系列学习总目录 本篇目录 开始一个新项目 没有AOP的生活 变更的代价 使用AOP重构 本系列的源码本人已托管于Coding上:点击查看. 本系列的实验环境:VS ...
- 基于Vue2.0+Vue-router构建一个简单的单页应用
爱编程爱分享,原创文章,转载请注明出处,谢谢!http://www.cnblogs.com/fozero/p/6185492.html 一.介绍 vue.js 是 目前 最火的前端框架,vue.js ...
随机推荐
- 【OpenCV新手教程之十四】OpenCV霍夫变换:霍夫线变换,霍夫圆变换合辑
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/26977557 作者:毛星云(浅墨) ...
- scikit-learn:class and function reference(看看你究竟掌握了多少。。)
http://scikit-learn.org/stable/modules/classes.html#module-sklearn.decomposition Reference This is t ...
- C语言的各种位运算符的操作简述
运算符: 算术运算符: + , - , * , / , % , ++ , -- 符合运算符: += , *= , /= , %= 条件运算符: ? : 关系运算符: == , >= , < ...
- Windows 7旗舰版安装Visual Studio 2013 Ultimate的系统必备及注意事项
系统必备: 1.Windows7 SP1 2.IE 10
- 导入别人的Android项目,提示 /Libs/gen already exists but is not a source folder. Convert to a source folder or rename it
解决方法: 遇到这个问题的解决方法: 1. 右键点击工程,选择 "Properties" 2. 选择左边的 "Java Build Path" 3. 打开 &q ...
- 不常见使用的css
flex和white-space等属性 1.flex属性让所有弹性盒模型对象的子元素都有相同的长度,忽略它们内部的内容.style={{flex:5}},该元素占父元素的六分之五. 2. white- ...
- Oracle - 创建表视图等 - DDL
解锁scott: sqlplus / as sysdba; alter user scott account unlock; alter user scott identified by tiger; ...
- idea把项目提交到svn服务器步骤
1.设置忽略文件.文件夹 2.找到以下选项 3.选择要上传项目的svn服务器地方和svn管理目录 4.填完相关提交信息,点击share就ok啦
- 转【前端基础进阶之Promise】
前言 Promise的重要性我认为我没有必要多讲,概括起来说就是必须得掌握,而且还要掌握透彻.这篇文章的开头,主要跟大家分析一下,为什么会有Promise出现. 在实际的使用当中,有非常多的应用场景我 ...
- Python3列表、元组、字典、集合的方法
一.列表 温馨提示:对图片点右键——在新标签页中打开图片: 1.count() 定义:统计指定元素在列表中出现的次数并返回这个数.若指定的元素不存在则返回:0. 格式:[列表].count(“指定元素 ...