如果说要做验证码,那不得不提的就是GDI+绘图了。我们都知道验证码是以图片形式展示的,而且是动态生成的,这样就需要我们去画出它。

科普一下,什么是GDI+?

GDI+是图形设备接口(GDI)的高级版本, 提供了各种丰富的图形图像处理功能。GDI+主要由二维矢量图形、图像处理和版式3部分组成。GDI+为使用各种字体、字号和样式来显示文本这种复杂任务提供了大量的支持。

下面说说验证码,对于验证码这样的图片,我觉得是由两部分组成的,一部分是矩形的背景,另一部分是在其上的字母数字组合(有的时候有汉字,有的时候是纯字母或者纯数字,这个没有统一规定,怎么选择看你~)。对于矩形的背景我们可以直接把其当成画布,字母数字组合呢?我们可以利用随机数去拼出一组新组合。这样整个过程我们都想好了,下面看下代码吧:

声明一下,我写的这个验证码为5个字符长度,由大小写英文字母+数字随机组合。

        private readonly char[] constant =  {
'0','1','2','3','4','5','6','7','8','9',
'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'};//一个由数字和大小写英文字母组成的字符数组 protected void Page_Load(object sender, EventArgs e)
{
Bitmap bitmap = new Bitmap(100, 25);//创建一个位图,宽100,高25,就是我所说的第一部分,矩形背景
Graphics g = Graphics.FromImage(bitmap);//创建画布
g.Clear(Color.YellowGreen);//为画布填充黄绿色 Font font1 = new Font("Arial", 15);//设置字体类型和大小
Brush brush = new SolidBrush(Color.Blue);//设置画刷颜色
Pen myPen = new Pen(Color.Blue, 5);//创建画笔对象 StringBuilder random = new StringBuilder(5); //创建可变字符串对象,用于存放随机生成的验证码
Random rd = new Random();//创建一个随机数生成器对象
for (int i = 0; i < random.Capacity; i++)
{
random.Append(constant[rd.Next(62)]);//生成一个随机字符加到random里
} g.DrawString(random.ToString(), font1, brush, 10, 5);//在画布上画出字符串 System.IO.MemoryStream ms = new System.IO.MemoryStream();//创建数据流MemoryStream
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);//指定图像的输出格式为gif Response.ClearContent();
Response.ContentType = "image/Gif";
Response.BinaryWrite(ms.ToArray());//输出二进制数据流
}

生成的效果是这样的:

大家可能会觉得这样看起来很容易辨识,跟我们平时登录网站时输入的验证码比起来有点像个小学生。当然,我们可以做些改变,比较加上一定的角度。

        private readonly char[] constant =  {
'0','1','2','3','4','5','6','7','8','9',
'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'};//一个由数字和大小写英文字母组成的字符数组 protected void Page_Load(object sender, EventArgs e)
{
Bitmap bitmap = new Bitmap(100, 25);//创建一个位图,宽100,高25,就是我所说的第一部分,矩形背景
Graphics g = Graphics.FromImage(bitmap);//创建画布
g.Clear(Color.YellowGreen);//为画布填充黄绿色 Font font1 = new Font("Arial", 15);//设置字体类型和大小
float angle = 60;//旋转的一个基础角度
float length = 0;//显示字符的基础位置,往后看
Brush brush = new SolidBrush(Color.Blue);//设置画刷颜色
Pen myPen = new Pen(Color.Blue, 5);//创建画笔对象 StringBuilder random = new StringBuilder(5); //创建可变字符串对象,用于存放随机生成的验证码
Random rd = new Random();//创建一个随机数生成器对象
for (int i = 0; i < random.Capacity; i++)
{
random.Append(constant[rd.Next(62)]);//生成一个随机字符加到random里 g.ResetTransform();//将画布重置矩阵
SizeF size = g.MeasureString(random[random.Length - 1].ToString(), font1);//得到新生成字符的尺寸
g.TranslateTransform(length + size.Width / 2, size.Height / 2);//选择此次旋转的中心位置
g.RotateTransform((float)rd.NextDouble() * angle * 2 - angle);//进行随机角度旋转
g.DrawString(random[random.Length - 1].ToString(), font1, brush, new PointF(-size.Width / 2, -size.Height / 2));//注意,这里不是前一个例子,一次性把5个字符全部画出来,而是一个一个画
length += size.Width;//保证下次画字符的位置不会覆盖前一次的字符
} System.IO.MemoryStream ms = new System.IO.MemoryStream();//创建数据流MemoryStream
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);//指定图像的输出格式为gif Response.ClearContent();
Response.ContentType = "image/Gif";
Response.BinaryWrite(ms.ToArray());//输出二进制数据流
}

这时生成的效果是这样的:

是不是看起来更专业一些了呢?如果大家还是觉得不满意的话,可以看下GDI+的相关内容,通过添加一些噪点的元素,或者删除线这样子的东西来达到提高识别难度的目的,我这里就不一一列举啦。

关于如何画验证码我们说过了,但是还有两点问题我还是想多说一下。

1、我们实际输出的是一个二进制的流,如何做到显示到页面上与页面其他元素共存呢?

这里通用的一种方法就是把画验证码的这段代码放到一个独立的Web窗体页中,在另一个需要显示验证码的页面放一个<img>元素,把其src属性指向该验证码页的url。比如我写的一段是这样

<asp:Image ID="image_validatecode" runat="server" ImageUrl="~/PublicMethod/ValidateCode.aspx" style="padding-left:3px"/>

其实这里我是用大家通用的方法,不过我先前也有单独写一个web自定义控件,专门生成验证码使用,但是当拖入到页面中后运行,它还是会把页面其他元素给覆盖掉,具体原因我也不清楚。

2、验证码主要目的还是用于验证使用的,所以我们在用户名,密码是否合法外,同时也要判断当前输入的验证码是不是与图片上的验证码一致。

我上面的代码中并没有写这块,其实只要在随机生成最终验证码之后,把其值存入一个session中去就可以了。然后在判断用户名,密码的同时去比较一下这个session值就OK了。如:

Session["login_validate_code"] = random.ToString();

3、如何用户没有看清此张验证码,想换一张如何实现?

可以通过脚本给img元素的src属性重新赋值url实现,当然,麻烦点的话也可以使用ajax去实现。大家可以自己试试。

ASP.NET 如何做出简单的验证码的更多相关文章

  1. 学习笔记:利用GDI+生成简单的验证码图片

    学习笔记:利用GDI+生成简单的验证码图片 /// <summary> /// 单击图片时切换图片 /// </summary> /// <param name=&quo ...

  2. ThinkPHP简单的验证码实现

    ThinkPHP简单的验证码实现 写一个最简单的TP验证码. 写Controller 首先在Controller/IndexController.class.php(简称Index)文件中编辑: &l ...

  3. python 简单图像识别--验证码

    python  简单图像识别--验证码 记录下,准备工作安装过程很是麻烦. 首先库:pytesseract,image,tesseract,PIL windows安装PIL,直接exe进行安装更方便( ...

  4. C#之asp.net 及MVC 生成动态验证码:

    C#之asp.net 及MVC 生成动态验证码: 1.生成验证码字符串 // 随机生成指定长度的验证码字符串private string RandomCode(int length) { string ...

  5. Flask学习之旅--用 Python + Flask 制作一个简单的验证码系统

    一.写在前面 现在无论大大小小的网站,基本上都会使用验证码,登录的时候要验证,下载的时候要验证,而使用的验证码也从那些简简单单的字符图形验证码“进化”成了需要进行图文识别的验证码.需要拖动滑块的滑动验 ...

  6. Python 常用模块系列学习(1)--random模块常用function总结--简单应用--验证码生成

    random模块--random是一个生成器 首先: import random    #导入模块 print (help(random))    #打印random模块帮助信息 常用function ...

  7. python简单处理验证码,三分钟,不能再多了

    序言 大家好鸭, 又是我小熊猫啦 我们在做采集数据的时候,过快或者访问频繁,或者一访问就给弹出验证码,然后就蚌珠了~今天就给大家来一个简单处理验证码的方法 环境模块 Python和pycharm如果还 ...

  8. ASP.NET Core使用SkiaSharp实现验证码

    前言 本文并没有实现一个完成的验证码样例,只是提供了在当前.NET Core 2.0下使用Drawing API的另一种思路,并以简单Demo的形式展示出来. Skia Skia是一个开源的二维图形库 ...

  9. asp.net mvc(一) ----------简单封装成通用的List<T>集合

    asp.net mvc(一) 这些天开始学习asp.net mvc,用传统的asp.net已经快四的年了,刚开始接触asp.net mvc确认感觉有点不适应,主要体现在asp.net mvc的实现上. ...

随机推荐

  1. 【转】RESTful Web Services初探

    近几年,RESTful Web Services渐渐开始流行,大量用于解决异构系统间的通信问题.很多网站和应用提供的API,都是基于RESTful风格的Web Services,比较著名的包括Twit ...

  2. BI

    http://www.cnblogs.com/biwork/p/3276455.html http://www.cnblogs.com/biwork/p/3328879.html http://www ...

  3. Git设置及GitHub的使用

    把github上的help略略翻译一遍.备忘. First : 安装:ubuntu 下,终端输入命令: sudo apt-get install git-core git-gui git-doc Ne ...

  4. CListCtrl使用方法汇总

    回顾: 刚刚写完,因为是分期写的,所以最初想好好做一下的文章格式半途而废了~说的也许会有点啰嗦,但是所有的基础用到的技术细节应该都用到了. 如果还有什么疑问,请回复留言,我会尽力解答. 如果有错误,请 ...

  5. YTU 2621: B 继承 圆到圆柱体

    2621: B 继承 圆到圆柱体 时间限制: 1 Sec  内存限制: 128 MB 提交: 313  解决: 240 题目描述 定义了Circle圆形类,在此基础上派生出Cylinder圆柱体类. ...

  6. Microsoft.ACE.OLEDB.12.0 错误 上传读取Excel错误

    使用"Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + filePath + ";&quo ...

  7. 使用JAVA直观感受快速排序与冒泡排序的性能差异

    初学算法,肯定会编写排序算法 其中两个最为有名的就是冒泡排序和快速排序 理论上冒泡排序的时间复杂度为O(N^2),快速排序的时间复杂度为O(NlogN) 下面本门使用JAVA,分别编写三段排序程序 对 ...

  8. 多个MapReduce作业相互依赖时,使用JobControl进行管理

    要处理复杂关系的数据,一个工程里面绝对不止一个MapReduce作业,当有多个MapReduce作业时,       并且每个作业之间有依赖关系,所谓的依赖就是一个作业得到的结果是另外一个作业的输入, ...

  9. 微信开发小结-PHP

    功能点: 1.  网页授权获得微信用户信息 用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑. 注意点:Scope为snsapi_base 只能获 ...

  10. 模拟实现STL中的list

    #pragma once #include<iostream>using namespace std;#include<assert.h> template<class ...