一个GG/MM的彩色验证码图片(C#)

1、为什么要加验证码?

因为加了验证码可以防御别人攻击你的网站,举个例子:别人可以用webbrowser控件做一个模拟浏览器,并且模拟提交表单(模拟填写表单资料和点击提交按钮),那么你的服务器必须接收这些表单传过来的值,并且做判断,是否正确。这样一来,别人可以无限占用你的服务器资源,而且账号密码都不安全,万一被别人搞个循环1个1个账号轮询的话,很有可能让别人破解了你的资料信息,所以安全性稍微高点的网站登录都有彩色图片验证码。

 

2、为什么彩色验证码图片可以防御别人的攻击?

因为当别人用轮询技术模拟登录的时候,他并不知道你的验证码是什么,也获取不到,因为这是一张图片,电脑并不能识别里面的数字是什么(除非破解验证码里面的干扰,再利用相关的图片识别技术有可能读出验证码,这里先不扯这个)。读不出验证码就没有机会轮询访问了,当然我们后台判断的时候一定要先判断验证码是否正确,以防止占用服务器资源。

3、随机数 Code

 ①数字随机数

 

 1           ///   <summary>
 2           ///  数字随机数
 3           ///   </summary>
 4           ///   <returns></returns>
 5           private   string  GetRndNum()
 6          {
 7               string  code  =   string .Empty;
 8              Random random  =   new  Random();
 9               for  ( int  i  =   0 ; i  <   4 ; i ++ )
10              {
11                  code  =  code  +  random.Next( 9 ).ToString();
12              }
13               return  code;
14          }

②字符串随机数

 1           ///   <summary>
 2           ///  字符串验证码
 3           ///   </summary>
 4           ///   <returns></returns>
 5           private   string  GetRndStr()
 6          {
 7               string  Vchar  =   " 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 " ;
 8               string [] VcArray  =  Vchar.Split( ' , ' );
 9               string  checkCode  =   string .Empty;
10              Random rand  =   new  Random();
11               for  ( int  i  = 0 ; i  <   4 ; i ++ )
12              {
13                  rand  =   new  Random( unchecked (( int )DateTime.Now.Ticks)); // 为了得到不同的随机序列
14                   int  t  =  rand.Next(VcArray.Length); //  The exclusive upper bound of the random number to be generated. maxValue must be greater than or equal to zero,下标从0开始
15                  checkCode  +=  VcArray[t];
16              }
17               return  checkCode;
18          }

③中文随机数

 1           ///   <summary>
 2           ///  随机中文码
 3           ///   </summary>
 4           ///   <returns></returns>
 5           private   string  GetRndCh()
 6          {
 7              System.Text.Encoding gb  =  System.Text.Encoding.Default; // 获取GB2312编码页(表)
 8               object [] bytes  =  CreateRegionCode( 4 ); // 调用函数产生4个随机中文汉字编码
 9               string [] str  =   new   string [ 4 ];
10              System.Text.StringBuilder sb  =   new  System.Text.StringBuilder();
11               for  ( int  i  =   0 ; i  <   4 ; i ++ )
12              {
13                   // 根据汉字编码的字节数组解码出中文汉字
14                  str[i]  =  gb.GetString(( byte [])Convert.ChangeType(bytes[i],  typeof ( byte [])));
15                  sb.Append( str[i].ToString());
16              }
17               return  sb.ToString ();
18          }        
19 
20 
21           ///   <summary>
22           ///  产生随机中文汉字编码
23           ///   </summary>
24           ///   <param name="strlength"></param>
25           ///   <returns></returns>
26           private   static   object [] CreateRegionCode( int  strlength)
27          {
28               // 定义一个字符串数组储存汉字编码的组成元素
29               string [] rBase  =   new  String[ 16 ] {  " 0 " " 1 " " 2 " " 3 " " 4 " " 5 " " 6 " " 7 " " 8 " " 9 " " a " " b " " c " " d " " e " " f "  }; 
30              Random rnd  =   new  Random();
31               object [] bytes  =   new   object [strlength];
32 
33               for  ( int  i  =   0 ; i  <  strlength; i ++ )
34              {
35                   // 区位码第1位
36                   int  r1  =  rnd.Next( 11 14 );
37                   string  str_r1  =  rBase[r1].Trim();
38 
39                   // 区位码第2位
40                  rnd  =   new  Random(r1  *   unchecked (( int )DateTime.Now.Ticks)  +  i);
41                   int  r2;
42                   if  (r1  ==   13 )
43                  {
44                      r2  =  rnd.Next( 0 7 );
45                  }
46                   else
47                  {
48                      r2  =  rnd.Next( 0 16 );
49                  }
50                   string  str_r2  =  rBase[r2].Trim();
51 
52                   // 区位码第3位
53                  rnd  =   new  Random(r2  *   unchecked (( int )DateTime.Now.Ticks)  +  i); // 更换随机种子
54                   int  r3  =  rnd.Next( 10 16 );
55                   string  str_r3  =  rBase[r3].Trim();
56 
57                   // 区位码第4位
58                  rnd  =   new  Random(r3  *   unchecked (( int )DateTime.Now.Ticks)  +  i);
59                   int  r4;
60                   if  (r3  ==   10 )
61                  {
62                      r4  =  rnd.Next( 1 16 );
63                  }
64                   else   if  (r3  ==   15 )
65                  {
66                      r4  =  rnd.Next( 0 15 );
67                  }
68                   else
69                  {
70                      r4  =  rnd.Next( 0 16 );
71                  }
72                   string  str_r4  =  rBase[r4].Trim();
73 
74                   // 定义两个字节变量存储产生的随机汉字区位码
75                   byte  byte1  =  Convert.ToByte(str_r1  +  str_r2,  16 );
76                   byte  byte2  =  Convert.ToByte(str_r3  +  str_r4,  16 );
77 
78                   // 将两个字节变量存储在字节数组中
79                   byte [] str_r  =   new   byte [] { byte1, byte2 };
80 
81                   // 将产生的一个汉字的字节数组放入object数组中
82                  bytes.SetValue(str_r, i);
83              }
84               return  bytes;
85          }

4、现在有了素材(随机数),那么再加上图片和困扰就完成了彩色图片验证码--困扰背景+图片Code

 

 1           ///   <summary>
 2           ///  画图片的背景图,干扰
 3           ///   </summary>
 4           ///   <param name="checkCode"></param>
 5           ///   <returns></returns>
 6           private  Bitmap CreateImages( string  checkCode, string  type)
 7          {
 8               int  step = 0 ;
 9               if (type == " ch " )
10              {
11                 step = 5 ; // 中文字符比较大,所以字距要比较大
12              }
13               int  iwidth  =  ( int )(checkCode.Length  *  ( 13   +  step));
14              System.Drawing.Bitmap image  =   new  System.Drawing.Bitmap(iwidth,  22 );
15              Graphics g  =  Graphics.FromImage(image);
16 
17              g.Clear(Color.White); // 清除背景色
18 
19              Color[] c  =  { Color.Black, Color.Red, Color.DarkBlue, Color.Green, Color.Orange, Color.Brown, Color.DarkCyan, Color.Purple }; // 定义随机颜色
20 
21               string [] font  =  {  " Verdana " " Microsoft Sans Serif " " Comic Sans MS " " Arial " " 宋体 "  };
22              Random rand  =   new  Random();
23 
24               for  ( int  i  =   0 ; i  <   50 ; i ++ )
25              {
26                   int  x1  =  rand.Next(image.Width);
27                   int  x2  =  rand.Next(image.Width);
28                   int  y1  =  rand.Next(image.Height);
29                   int  y2  =  rand.Next(image.Height);
30                  g.DrawLine( new  Pen(Color.LightGray, 1 ), x1,y1,x2,y2); // 根据坐标画线
31              }
32 
33               for  ( int  i  =   0 ; i  <  checkCode.Length; i ++ )
34              {
35                   int  cindex  =  rand.Next( 7 );
36                   int  findex  =  rand.Next( 5 );
37 
38                  Font f  =   new  System.Drawing.Font(font[findex],  10 , System.Drawing.FontStyle.Bold);
39                  Brush b  =   new  System.Drawing.SolidBrush(c[cindex]);
40                   int  ii  =   4 ;
41                   if  ((i  +   1 %   2   ==   0 )
42                  {
43                      ii  =   2 ;
44                  }
45                  g.DrawString(checkCode.Substring(i,  1 ), f, b,  3   +  (i  *  ( 12   +  stepw)), ii);
46              }
47 
48              g.DrawRectangle( new  Pen(Color.Black,  0 ),  0 0 , image.Width  -   1 , image.Height  -   1 );
49 
50              System.IO.MemoryStream ms  =   new  System.IO.MemoryStream();
51               return  image;
52          }

5、总结

 根据你要的随机数和背景就可以返回BitMap数组,然后把BitMap数组以图片形式存到内存流,就可以返回了。在这里只提供思路与制作方法并没有提供全部代码与封装过程,若对代码有疑问或者需要实例可以加QQ群128584255,大家讨论学习一下。

你可能感兴趣的:(验证码)