关于ASP.NET中图片验证码使用的扫盲
先说说什么是验证码吧,它是一种区分用户是计算机和人的公共全自动程序。可以防止:恶意破解密码、刷票、论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试,实际上是用验证码是现在很多网站通行的方式(比如招商银行的网上个人银行,百度社区),我们利用比较简易的方式实现了这个功能。图片验证码嘛!嘿嘿,就是用图片的形式表述出来这个验证码喽!至于为什么用图片的形式表示下面说。
不知道大家有木有发现,有的时候上论坛,经常看见什么卖假烟啦,卖茶叶的,一发就是好几页的广告~这也就是没有验证码的原因。其实那些发布广告贴的用户也不是人手工发贴的,想想啊,那还不累死,为了5毛,不值得啊!都是利用一个发帖的小程序,批量发帖的,如果这个时候我们的ASP.NET网站使用了图片验证码技术的话,简单的发帖程序就没有办法帮主人工作了,整个世界都清净了,有木有?
还有就是多年前很流行(现在也很流行,但是应用的地方不一样了)传说中的暴力破解,所谓暴力破解,也就是没有什么技术含量,用一个暴力破解的程序,一直变化密码来试验,直到把这个密码试验出来,这个方法在理论上来说还是很牛b的,无论什么样的密码,都可因由暴力破解破解出来。不过话说回来,理论只是理论,但是破解的时间呢?可以想象,密码越长,试验的时间就越长。后来干坏事的人觉得,这破解的时间也太长了,等不及,就把大家经常用的密码形成一个字库,比如生日格式的,电话号码格式的等等,这样就大大的增加了破解的成功率以及破解所花的时间,有些人设置的密码还偏偏就是这样的弱类型密码,唉。。。。明知山有虎偏向虎上行啊~
好了好了,话题都扯远了,今天我就简单的介绍一下传说中ASP.NET中的图片验证码技术。
其实也不是很难,原理就是这样的,在用户提交信息到服务器之前做一个验证,就是我们动态生成的图片验证码,输入正确,就可以向服务器提交。有人就说了,我们这里为什么要用一张图片?用一串动态生成的字符密码岂不是更好,节省网络资源,提高网站的性能?哈哈~这里就是人和程序的不一样之处了,人能读懂各种资源,图片上的文字也不例外,如果只是网页中简单的一点字符,虽然人能明白是什么,但是程序也可以读出来啊!这样自动发帖或者暴力破解程序一样可以识别简单的字符啊!就违背了我们的初衷,所以这里使用的一定是图片验证码,这样程序要是想识别就难喽~
好了,现在看看具体实现的过程,这里只是一个简单的例子,如果应用在网站中需要考虑的就不只是这么简单了,这里只是图片验证码技术的一个原理哦~
第一看看我们需要用到的东西。
第一个就是C#中的Random类,它是表示伪随机数生成器,一种能够产生满足某些随机性统计要求的数字序列的。说白了,既然是验证码,就要有一个随机动态产生的一串字符,用它作为验证码,C#中的Random类就是我们用来生成验证码的类。我们这里只要使用它的Next()方法,这个方法会返回一个随机的正整数。
第二个就是Session,它提供对会话状态值以及会话级别设置和生存期管理方法的访问。Session 是 用于保持状态的基于 Web 服务器的方法。Session 允许通过将对象存储在 Web 服务器的内存中在整个用户会话过程中保持任何对象。Session 的作用就是它在 Web 服务器上保持用户的状态信息供在任何时间从任何页访问。因为浏览器不需要存储任何这种信息,所以可以使用任何浏览器,即使是像 PDA 或手机这样的浏览器设备。所以这里,我们就把用Random生成的验证码存储在Session中,方便我们使用。
第三就是C#中的Bitmap类,它封装 GDI+ 位图,此位图由图形图像及其特性的像素数据组成。 Bitmap 是用于处理由像素数据定义的图像的对象。说白了就是用它创建一张图片,并且做出一些修改。
第四个就是Graphics类,它封装一个GDI+绘图图面,我们主要用它的DrawString()方法,在图片上写上我们的验证码。
好了,用到的东西不多,就这四个,我们开始Coding吧!
第一步,实例化一个stirng类型的变量备用,一会儿我们把我们生成的验证码存在里面。这个,就不做过多介绍了。
1 string str;
第二步,用Random.next(0,100)得到三个0-100之间的随机数,把他们拼到一起,存在第一步实例化好的string变量中,这就是什么的验证码了,老鸟可能说了,这个验证码是不是太简单了?当然是的!这里说的就是一个原理,以后应用中我们可以利用Random出来的整数生成很多字符,比如把得到的随机数用ASCII码的方式转换成大、小写的字符,甚至符号都可以,这里为了方便说明,所以就只用3个随机获得的整数作为验证码吧。
这里介绍一下rand.next(x,y)这个方法就是说返回一个正整数,它大于x并且小于y。
1 Random rand = new Random(); 2 int v1 = rand.Next(0, 100); 3 int v2 = rand.Next(0, 100); 4 int v3 = rand.Next(0, 100); 5 str = v1.ToString() + v2.ToString() + v3.ToString();
第三步,把生成好的string验证码放在Session中备用。
1 Context.Session["Code"] = str;
第四步,实例化一个Bitmap类,作为我们的画板,这里我用了一张空白的图片,方便一会儿在上面写写画画~
这里实例化Bitmap的时候我们的参数是一张图片的地址,意识是从指定的现有图像初始化 Bitmap 类的新实例。
1 Bitmap bitmap = new Bitmap(Context.Server.MapPath("~/Image/1.jpg"));
第五步,实例化一个Graphics类,备用作为一个画笔,在一会儿画图片的时候用。
这里可以看出,实例化Graphics类的时候我们用到的方法是FromImage(),顾名思义,从指定的现有图像初始化 Bitmap 类的新实例。
1 Graphics g = Graphics.FromImage(bitmap);
第六步,把Random到的验证码用DrawString方法画在刚刚实例化的Bitmap上。
这里用到的DrawString()意思方法是在指定位置并且用指定的 Brush 和 Font 对象绘制指定的文本字符串。具体参数是这样DrawString(字符串,字体,颜色,横竖坐标)。
1 g.DrawString(str, new Font("黑体", 15), Brushes.Red, 0, 0);
第七步,用Bitmap类的SetPixe方法在画好验证码的图片上画一些点点,这样只有人才能看懂了吧?当然,颜色的选择这里也是Random得到的。
这里还是用到了rand.Next,不过这次的参数只有一个rand.Next(x),意思是返回一个值不大于x的正整数,可以想象,如果大于图片也就是我们的画布的大小,我们往哪里画呢?还有就是bitmap.SetPixel()上面已经说过,这个方法是在画布上画小点点,它本身是不会“画”东西的,只是改变了给定位置像素的颜色,也就达到了我们的目的,具体的参数是这样的SetPixel(x坐标,y坐标,颜色),这里的颜色也是用rand随机得到的一个颜色,FromArgb方法故名思议就是指定 32 位 ARGB 值的值。我在这里画了300个。
1 for (int i = 0; i < 300; i++) 2 { 3 int x = rand.Next(bitmap.Width); 4 int y = rand.Next(bitmap.Height); 5 bitmap.SetPixel(x,y,Color.FromArgb(rand.Next())); 6 }
最后一步,我们保存生成好的图片验证码吧!
1 bitmap.Save(Context.Server.MapPath("~/Image/2.jpg"));
来吧,看看完整的方法:
1 public void createImage() 2 { 3 string str; 4 Random rand = new Random(); 5 int v1 = rand.Next(0, 100); 6 int v2 = rand.Next(0, 100); 7 int v3 = rand.Next(0, 100); 8 str = v1.ToString() + v2.ToString() + v3.ToString(); 9 Context.Session["Code"] = str; 10 Bitmap bitmap = new Bitmap(Context.Server.MapPath("~/Image/1.jpg")); 11 Graphics g = Graphics.FromImage(bitmap); 12 g.DrawString(str, new Font("黑体", 15), Brushes.Red, 0, 0); 13 for (int i = 0; i < 300; i++) 14 { 15 int x = rand.Next(bitmap.Width); 16 int y = rand.Next(bitmap.Height); 17 bitmap.SetPixel(x,y,Color.FromArgb(rand.Next())); 18 } 19 bitmap.Save(Context.Server.MapPath("~/Image/2.jpg")); 20 }
嘿嘿,看看其实很简单就完成了,最后看看效果:
还不错吧~这就是传说中的验证码啦~对了,今天2012-10-24,是传说中的程序员节哦~祝所有的程序员节日快乐哦~也几年我在博客园的第一篇随笔~就到这里了!