本文的学习流程是这样安排的。

一个简单的GDI小案例

1.说明

如果你想思考如何生成验证码,那么您第一个要解决的问题,一定是.NET动态生成图片问题。

//GDI:.Net程序中进行绘图的一些类。

2.代码

 1             //这段代码开始前,要添加System.Drawing的引用。
 2             //创建一个尺寸为500*500的内存图片
 3             using (Bitmap bmp = new Bitmap(500, 500))
 4             //得到图片的画布
 5             using (Graphics g = Graphics.FromImage(bmp))
 6             {
 7                 //创建画笔
 8                 using (Font font = new Font(FontFamily.GenericSerif, 30))
 9                  {
10                       //在100,100处画一个红色的helloWorld
11                       g.DrawString("HelloWorld", font, Brushes.Red, 100, 100);
12                       //在100,100处画一个蓝色的椭圆
13                       g.DrawEllipse(Pens.Blue, 100, 100, 100, 100);
14
15                       using (Stream stream = File.OpenWrite(@"d:\2.jpg"))
16                       {
17                             bmp.Save(stream, ImageFormat.Jpeg);
18                        }
19                  }
20             } 

看这就生成完了。代码上,貌似没什么需要解释的。

用一般处理程序返回一个图片

1.说明

接下来我们研究一下如何在网页中动态生成一个图片。

从代码的角度上看。跟上边控制台上的代码仅有几点简单区别,几乎一样!

1)一般处理程序需要先设置ContentType =“image/jpeg”

2)一般处理程序需要把图片保存到Response.OutputStream中

2.代码

 1             context.Response.ContentType = "image/jpeg";
 2
 3             //这段代码开始前,要添加System.Drawing的引用。
 4             //创建一个尺寸为500*500的内存图片
 5             using (Bitmap bmp = new Bitmap(500, 500))
 6             //得到图片的画布
 7             using (Graphics g = Graphics.FromImage(bmp))
 8             {
 9                 //创建画笔
10                 using (Font font = new Font(FontFamily.GenericSerif, 30))
11                  {
12                       //在100,100处画一个红色的helloWorld
13                       g.DrawString("HelloWorld", font, Brushes.Red, 100, 100);
14                       //在100,100处画一个蓝色的椭圆
15                       g.DrawEllipse(Pens.Blue, 100, 100, 100, 100);
16                       //图片保存到输出流
17                       bmp.Save(context.Response.OutputStream, ImageFormat.Jpeg);
18
19                  }
20             } 

简单的数字验证码

1.思维

既然我们已经解决了如何动态生成图片,和如何在一般处理程序中返回一个图片的问题。

那么做验证码的技术问题,只剩下了如何生成四位随机数了。

其实就是用Random生成 1000~9999之间的随机数。

然后把这个四位数放到Session中,在根据这个数字生成验证码图片。

这就是生成验证码的基础逻辑了。

2.代码

 1 public void ProcessRequest(HttpContext context)
 2         {
 3             context.Response.ContentType = "image/jpeg";
 4
 5             Random random = new Random();
 6             //生成随机数
 7             string code = random.Next(1000, 9999).ToString();
 8             //把验证码放到Session中,方便以后比对
 9             context.Session["checkCode"] = code;
10             //开始生成验证码的图片
11             using (Bitmap bmp = new Bitmap(130, 50))
12             using (Graphics g = Graphics.FromImage(bmp))
13             {
14                 using (Font font = new Font(FontFamily.GenericSerif, 30))
15                 {
16                     g.DrawString(code, font, Brushes.AliceBlue, 10, 10);
17                     //图片保存到输出流
18                     bmp.Save(context.Response.OutputStream, ImageFormat.Jpeg);
19                 }
20             }
21         }

生成效果(当然这样的验证码,稍微懂一点图形学的人都能用程序读取出来,开发中千万别这么干!)

3.节外生枝

本来我敲着代码唱这歌,挺happy的,结果突然就给我报了一个空引用的异常,这里有必要说一下。

稍微复杂一点的验证码

1.思路

我的改进思路是这样的。

1)既然随机生成数字太简单,觉得说不过去。那就随机生成5个字符。

字符写在一个数组里。随机生成数组下标,然后拿出五个。字符数组我们可以写的复杂一点。

2)生成图片以后,在图片上随手扔点躁点,增加其他程序的识别成本。

2.代码

 1 public void ProcessRequest(HttpContext context)
 2      {
 3          string checkCode = GenCode(5);  // 产生5位随机字符
 4          context.Session["Code"] = checkCode; //将字符串保存到Session中,以便需要时进行验证
 5          System.Drawing.Bitmap image = new System.Drawing.Bitmap(70, 22);
 6          Graphics g = Graphics.FromImage(image);
 7          try
 8          {
 9              //生成随机生成器
10              Random random = new Random();
11              //清空图片背景色
12              g.Clear(Color.White);
13              // 画图片的背景噪音线
14              int i;
15              for (i = 0; i < 25; i++)
16              {
17                  int x1 = random.Next(image.Width);
18                  int x2 = random.Next(image.Width);
19                  int y1 = random.Next(image.Height);
20                  int y2 = random.Next(image.Height);
21                  g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2);
22              }
23
24              Font font = new System.Drawing.Font("Arial", 12, (System.Drawing.FontStyle.Bold));
25              System.Drawing.Drawing2D.LinearGradientBrush brush =  new System.Drawing.Drawing2D.LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Blue, Color.DarkRed, 1.2F, true);
26              g.DrawString(checkCode, font, brush, 2, 2);
27              //画图片的前景噪音点
28              g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1);
29              System.IO.MemoryStream ms = new System.IO.MemoryStream();
30              image.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
31              context.Response.ClearContent();
32              context.Response.ContentType = "image/Gif";
33              context.Response.BinaryWrite(ms.ToArray());
34          }
35          finally
36          {
37              g.Dispose();
38              image.Dispose();
39          }
40      }
41
42 /// <summary>
43 /// 产生随机字符串
44 /// </summary>
45 /// <param name="num">随机出几个字符</param>
46 /// <returns>随机出的字符串</returns>
47      private string GenCode(int num)
48      {
49          string str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
50          char[] chastr = str.ToCharArray();
51          // string[] source ={ "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", "#", "$", "%", "&", "@" };
52          string code = "";
53          Random rd = new Random();
54          int i;
55          for (i = 0; i < num; i++)
56          {
57              //code += source[rd.Next(0, source.Length)];
58              code += str.Substring(rd.Next(0, str.Length), 1);
59          }
60          return code;
61      }

生成效果。差不多能用了吧?

好了今天的关于验证码的问题就说这些了。

我还是那个观点,这种东西没有必要记住,当然如果真能上手就写,那自然是极好的。

记不住也不影响开发,写的时候上网搜一下就好了。

之所以要写这篇文章有两个原因。

1) 总要有人写这种东西,要不去哪复制。自己写一篇以后也好找。

2) 毫无了解的代码,即使复制下来就能用,但是使用起来是心虚的。

(当然这一点不绝对,太难的东西就算了。还是有太多东西我们是,不需要了解的。

ASP.NET内核几大对象、ASP.NET核心知识(7)--转载的更多相关文章

  1. ASP.NET内核几大对象、ASP.NET核心知识(6)--转载

    这篇博文主要介绍一下几个对象. 1)HttpContext 2)HttpRequest 3)HttpResponse 4)context. Server 5)context.Session HttpC ...

  2. ASP.NET内核几大对象、ASP.NET核心知识(6)

    描述 其实今天的博文,是一般处理程序的后续部分,理论上应该叫一般处理程序().但是觉得文章标题后面的系列名已经有个数字,再加一个2有点怪. 这篇博文主要介绍一下几个对象. )HttpContext ) ...

  3. 18第一章 ASP.Net内建对象

    第一章        ASP.Net内建对象 第一章        ASP.Net内建对象 ASP.Net为保持用户的数据和信息,内建了许多对象,包括Application.Response.Requ ...

  4. Asp.net有三大对象:HttpContext, HttpRequest, HttpResponse

    一.Asp.net有三大对象:HttpContext, HttpRequest, HttpResponse.命名空间:  System.Web程序集:  System.Web(在 System.Web ...

  5. Cookie详解、ASP.NET核心知识(7)

    无状态的http协议 1.回顾http协议 Http协议是请求响应式的,有请求才有响应,是无状态的,不会记得上次和网页“发生了什么”. 关于http协议的这种特点,黑兔在前面的这三篇博文中进行了详细的 ...

  6. 网络基础知识、ASP.NET 核心知识(1)*

    为什么要写网络? 我原本的计划是这样的,连续两天梳理ASP.NET开发的核心知识.说到这呢,有人问了.“不是说好了做ASP.NET笔记吗?为啥要写网络基础知识?是不是傻?” 原因是这样的.作为网站开发 ...

  7. ASP.NET中application对象

    ASP.NET中application对象的使用. Application对象的应用  1.使用Application对象保存信息  (1).使用Application对象保存信息  Applicat ...

  8. 初识 Asp.Net内置对象之Response对象

    Response对象 Respose对象用于将数据从服务器发送回浏览器.它允许将数据作为请求的结果发送到浏览器,并提供有光响应的信息,可以用来在页面中输入数据,在页面中跳转,还可以传递各个页面的参数, ...

  9. ASP.NET 内置对象涉略

    一.ASP.NET中内置的常用对象的介绍 本文列举了ASP.NET 的八个内置对象,其中前五个是比较常用的. 1.Response Response 对象用于从服务器向用户发送输出的结果. Write ...

随机推荐

  1. AVD启动不了 ANDROID_SDK_HOME is defined but could not find *.ini

    报错提示______________________________________________________________________ Starting emulator for AVD ...

  2. .NET 笔试分享

    最近一直在面试,每次面试前也不怎么准备,虽说碰到的题大部分都很简单的,但是在现场答题的时候由于自己紧张脑子就空了,一些题答的不是很好,所以只有每次回来的时候才能好好想想怎么答: 题大部分还是挺简单的, ...

  3. VPN错误789:L2TP连接尝试失败

    VPN 错误789:l2tp 连接尝试失败,因为安全层在初始化与远程计算机的协商时遇到一个处理错误 Windows配置VPN,选择“使用IPsec的第2层隧道协议(L2TP/IPSec)”时, XP系 ...

  4. idea导入项目出错

    在idea导如项目后,总是会报错,每个类都会报错.解决的办法是: 1. 2.添加本地jdk 3.添加项目中的lib包

  5. mysqlbinlog恢复数据

    操作命令: 复制代码代码如下: show binlog events in 'mysql-bin.000016' limit 10; reset master 删除所有的二进制日志flush logs ...

  6. iOS 8以上的设置的跳转

    iOS8以上的系统应用可以与设置进行深层的交互,用户可以根据APP的需要进行对应的权限的设置. 现在大多数的APP依旧仅仅是弹出一个包含操作指令的警示窗口,如“进入设置>隐私>位置> ...

  7. 为什么要用Math.sqrt(i)方法

    java 练习题 判断 101-200 之间有多少个素数,并输出所有素数 public class Prime { public static int count = 0; public static ...

  8. LoadRunner参数化功能详解

    更新方式: .      Each Occurrence 每次遇到参数就进行更新. 多次使用同一参数,而且没有什么关联,例如随机数. Each Iteration 每次迭代时发生更新. 如果参数出现几 ...

  9. python 反向查找

    python 字符串反向查找大部分在正向查找前面加入r eg: str.rfind('str') str.rsplit(',')

  10. Is there a complete List of JVM exit codes

    Argument passed to System.exit(x) -> becomes the JVM exit code. Exit code 0 is used to indicate n ...