概述
几年前,大部分网站、论坛之类的是没有验证码的,因为对于一般用户来说验证码只是增加了用户的操作,降低了用户的体验。但是后来各种灌水机器人、投票机器人、恶意注册机器人层出不穷,大大增加了网站的负担同时也给网站数据库带来了大量的垃圾数据。为了防止各种机器人程序的破坏,于是程序员想出了只有人眼能够识别的,程序不容易识别的验证码!
验证码是一个图片,将字母、数字甚至汉字作为图片的内容,这样一张图片中的内容用人眼很容易识别,而程序将无法识别。在进行数据库操作之前(比如登录验证、投票、发帖、回复、注册等等)程序首先验证客户端提交的验证码是否与图片中的内容相同,如果相同则进行数据库操作,不同则提示验证码错误,不进行数据库操作。这样各种机器人程序就被拒之门外了!
验证码使用
验证码是针对各种机器人程序的,所以验证码图片中的内容是不能存放在Cookie、HTML和URL中的
代码实现
引用nuget包
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
创建VierificationCodeServices
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;namespace CompanyName.ProjectName.Core
{/// <summary>/// 验证码/// </summary>public class VierificationCodeServices{/// <summary>/// 该方法用于生成指定位数的随机数/// </summary>/// <param name="VcodeNum">参数是随机数的位数</param>/// <returns>返回一个随机数字符串</returns>private static string RndNum(int VcodeNum){//验证码可以显示的字符集合string Vchar = "0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,g,h,i,j,k,l,m,n,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,P,P,Q" +",R,S,T,U,V,W,X,Y,Z";string[] VcArray = Vchar.Split(new Char[] { ',' });//拆分成数组string code = "";//产生的随机数int temp = -1;//记录上次随机数值,尽量避避免生产几个一样的随机数Random rand = new Random();//采用一个简单的算法以保证生成随机数的不同for (int i = 1; i < VcodeNum + 1; i++){if (temp != -1){rand = new Random(i * temp * unchecked((int)DateTime.Now.Ticks));//初始化随机类}int t = rand.Next(61);//获取随机数if (temp != -1 && temp == t){return RndNum(VcodeNum);//如果获取的随机数重复,则递归调用}temp = t;//把本次产生的随机数记录起来code += VcArray[t];//随机数的位数加一}return code;}/// <summary>/// 该方法是将生成的随机数写入图像文件/// </summary>/// <param name="code">code是一个随机数</param>/// <param name="numbers">生成位数(默认4位)</param>public static MemoryStream Create(out string code, int numbers = 4){code = RndNum(numbers);Bitmap Img = null;Graphics g = null;MemoryStream ms = null;Random random = new Random();//验证码颜色集合Color[] c = { Color.Black, Color.Red, Color.DarkBlue, Color.Green, Color.Orange, Color.Brown, Color.DarkCyan, Color.Purple };//验证码字体集合string[] fonts = { "Verdana", "Microsoft Sans Serif", "Comic Sans MS", "Arial", "宋体" };//定义图像的大小,生成图像的实例Img = new Bitmap((int)code.Length * 18, 32);g = Graphics.FromImage(Img);//从Img对象生成新的Graphics对象g.Clear(Color.White);//背景设为白色//在随机位置画背景点for (int i = 0; i < 100; i++){int x = random.Next(Img.Width);int y = random.Next(Img.Height);g.DrawRectangle(new Pen(Color.LightGray, 0), x, y, 1, 1);}//验证码绘制在g中for (int i = 0; i < code.Length; i++){int cindex = random.Next(7);//随机颜色索引值int findex = random.Next(5);//随机字体索引值Font f = new Font(fonts[findex], 15, FontStyle.Bold);//字体Brush b = new SolidBrush(c[cindex]);//颜色int ii = 4;if ((i + 1) % 2 == 0)//控制验证码不在同一高度{ii = 2;}g.DrawString(code.Substring(i, 1), f, b, 3 + (i * 12), ii);//绘制一个验证字符}ms = new MemoryStream();//生成内存流对象Img.Save(ms, ImageFormat.Jpeg);//将此图像以Png图像文件的格式保存到流中//回收资源g.Dispose();Img.Dispose();return ms;}}
}
生成ValidateCode
/// <summary>/// 图形验证码/// </summary>/// <returns></returns>public IActionResult ValidateCode(){string code = "";MemoryStream ms = VierificationCodeServices.Create(out code);HttpContext.Session.SetString("LoginValidateCode", code);Response.Body.Dispose();return File(ms.ToArray(), @"image/png");}