[ASP.NET] 图形验证码破解-以简单图形为例

原文 http://www.dotblogs.com.tw/joysdw12/archive/2013/06/08/captcha-cracked.aspx

前言



  这次来讲个比较有趣的主题,就是该如何破解网路上那些防止机器人攻击的图形验证码,谈到图形验证码破解,想必各位嘴角一定微微上扬了吧XD,看来学坏好像都比较有兴趣一点,但其实知道破解的原理后,之后要做防范也比较清楚该如何处理了← 主因:P。

 

  在开始破解前先来看一下基本上的破解原理与方法,可以先参考此篇  使用PHP对网站验证码进行破解 文章,文章中提到了破解图形验证码有几个基本步骤,如下:

  1. 取出字模
  2. 二值化
  3. 计算特征
  4. 对照样本

 

Step 1 取出字模

  首先取出字模就是将要破解的图形验证码先抓取回来,而取得的字模图片必须要包含所有会出现的文字,例如0 - 9 的数字图片,当有了字模后就能够将字模进行二值化。

 

Step 2 二值化

  二值化是什么? 二值化就是将数字字模转换成0 与1 的结果,将图片上数字的部分用1 替换而0 则代表背景,例如我有一张数字3 的图片,在经过二值化后就会变成以下结果。

000000000000000000000 
000000011111100000000 
000001110001110000000 
000000000000111000000 
000000000000110000000 
000000011111100000000 
000000000000110000000 
000000000000111000000 
000001110001110000000 
000000011111000000000 
000000000000000000000

 

Step 3 计算特征

  当我们将图片数字转成二值化后,这些二值化的01 代码就变成了样本库,所以在计算特征的步骤里,就是要在产生验证码的页面将验证码图片取得,取得后因为验证码可能包含干扰元素,就必须要先去除干扰元素后将图片二值化取得特征。

 

Step 4 对照样本

  最后的步骤就是要将第三步骤二值化的值拿去比对我们的样本库,通常在比对的时候一定会产生误差值,例如以下转换后的二进值:

000000000000000000000 
000000011111100000000 
0000 1 111000111 1 000000 
000000000000111000000 
000000000000110000000 
000000011111100000000 
000000000000110000000 
000000000000111000000 
000001110001110000000 
0000000111110000 1 0000 
000000000000000000000

 

  可以看到以上二进值红色的1 的部分就是所谓的噪点,因为图片在不同的位置下所产生的图片像素可能会不一样,所以我们在对照样本时可以设定一个允许容忍噪点的范围,就是有点模糊比对的意思。

 

实作破解



  接下来的说明将使用  [VB]使用图形验证码范例  此文章的产生方式来举例说明,先举例以下三种图形验证码样式说明,如下:

 

  • 第一种是没有任何干扰单纯只有数字的验证码,这种验证码非常容易破解,只需要将图片进行灰阶处理后再分别取出单元字块比对即可。
  • 第二种是多加了噪音线干扰的验证码,其实这个噪音线有跟没有一样,一样只要经过灰阶处理后再针对噪音线的像素去除即可破解。
  • 第三种是多加了噪音点干扰的验证码,这种验证码破解处理就比较麻烦点,需要针对噪音点的周围判断是否能去除,但是其实只要有足够的样本可以对照也是可以破解的。

 

  除了 ​​以上举例的这几种外,在 Caca Labs  也有举出好几种验 ​​证码格式与能够破解的机率表,可以去看一看,接下来就开始实作破解,以下范例使用到Web与AP,透过AP浏览网页并抓取网页内的验证码图形处理破解。

 

取得验证码图形

  第一步首先要取得验证码的图片,因为破解主要使用AP 处理,所以在这里我们可以使用WebBrowser 类别搭配Microsoft.mshtml 命名空间处理,在WebBrowser 网页载入完成触发的DocumentCompleted 事件中取得图片并转换成Bitmap 型别做后续处理,如下代码:

01 private void webBrowser1_DocumentCompleted( object sender, WebBrowserDocumentCompletedEventArgs e)
02 {
03     WebBrowser wb = sender as WebBrowser;
04     var doc = wb.Document.DomDocument as HTMLDocument;
05     HTMLBody body = doc.body as HTMLBody;
06     IHTMLControlRange range = body.createControlRange();
07     // 取得网页上验证码图片
08     IHTMLControlElement imgElement =
09         wb.Document.GetElementById( "imgCaptcha" ).DomElement as IHTMLControlElement;
10     range.add(imgElement);
11     range.execCommand( "copy" false , Type.Missing);
12     Image img = Clipboard.GetImage();
13     Clipboard.Clear();
14     picBox1.Image = img;
15     // 转换成Bitmap 物件进行破解
16     CaptchaCracked( new Bitmap(img));
17     // 将验证码写入文字框
18     wb.Document.GetElementById( "txtCaptchaCode" ).SetAttribute( "value" , txtCode.Text);
19 }

 

第一种图形破解

  先来看看第一种图形该如何破解,第一种图形非常没有挑战性,我们要先撰写针对验证码处理的相关代码,产生一个CaptchaCrackedHelper 类别,并加入一些属性配置。

01 public class CaptchaCrackedHelper
02 {
03     /// <summary>
04     /// 存放来源图档
05     /// </summary>
06     public Bitmap BmpSource { get set ; }
07     /// <summary>
08     /// 区分背景与数字的灰阶值
09     /// </summary>
10     private int GrayValue { get set ; }
11     /// <summary>
12     /// 可容忍的错误噪点数
13     /// </summary>
14     private int AllowDiffCount { get set ; }
15     /// <summary>
16     /// 对照样本字典
17     /// </summary>
18     private DecCodeList DecCodeDictionary { get set ; }
19      
20     public CaptchaCrackedHelper() { }
21     public CaptchaCrackedHelper(
22         Bitmap pBmpSource, int pGrayValue, int pAllowDiffCount, DecCodeList pDecCodeDictionary)
23     {
24         BmpSource = pBmpSource;
25         GrayValue = pGrayValue;
26         AllowDiffCount = pAllowDiffCount;
27         DecCodeDictionary = pDecCodeDictionary;
28     }
29 }

 

  第二步骤,因为原始图片可能包含很多色彩,而之后的判断是使用灰阶值的高低来做为区分数字或背景的依据,所以要将图片先进行灰阶处理,加入灰阶处理方法,如下

01 /// <summary>
02 /// 将每点像素色彩转换成灰阶值
03 /// </summary>
04 public void ConvertGrayByPixels()
05 {
06     for int i = 0; i < BmpSource.Height; i++)
07         for int j = 0; j < BmpSource.Width; j++)
08         {
09             int grayValue = GetGrayValue(BmpSource.GetPixel(j, i));
10             BmpSource.SetPixel(j, i, Color.FromArgb(grayValue, grayValue, grayValue));
11         }
12 }
13  
14 /// <summary>
15 /// 计算灰阶值
16 /// </summary>
17 /// <param name="pColor">color-像素色彩</param>
18 /// <returns></returns>
19 private int GetGrayValue(Color pColor)
20 {
21     return Convert.ToInt32(pColor.R * 0.299 + pColor.G * 0.587 + pColor.B * 0.114); //灰阶公式
22 }

 

  第三步骤,灰阶处理后接下来就要重新取得图片的范围,因为之后必须要将图片切割成一个数字一张图,所以要去除掉多余的空白处,如下

01 /// <summary>
02 /// 转换图片有效范围
03 /// </summary>
04 /// <param name="pCharsCount">int-字元数量</param>
05 public void ConvertBmpValidRange( int pCharsCount)
06 {
07     // 图片最大X, Y,处理后变成起始X, Y
08     int posX1 = BmpSource.Width, posY1 = BmpSource.Height;
09     // 图片起始X, Y,处理后变成最大X, Y
10     int posX2 = 0, posY2 = 0;
11  
12     // 取得有效范围区域
13     for int i = 0; i < BmpSource.Height; i++)
14     {
15         for int j = 0; j < BmpSource.Width; j++)
16         {
17             int pixelVal = BmpSource.GetPixel(j, i).R;
18             if (pixelVal < GrayValue) //如像该素值低于指定灰阶值则进行缩小区域
19             {
20                 if (posX1 > j) posX1 = j; //如X2像素位置大于图片宽度则缩小宽度
21                 if (posY1 > i) posY1 = i; //如Y2像素位置大于图片高度则缩小高度
22                 if (posX2 < j) posX2 = j; //如X1像素位置小于图片宽度则缩小宽度
23                 if (posY2 < i) posY2 = i; //如Y1像素位置小于图片宽度则缩小宽度
24             }
25         }
26     }
27  
28     // 确保图片可以平均切割图片
29     int span = pCharsCount - (posX2 - posX1 + 1) % pCharsCount;
30     if (span < pCharsCount)
31     {
32         int leftSpan = span / 2;
33         if (posX1 > leftSpan)
34             posX1 = posX1 - leftSpan;
35         if (posX2 + span - leftSpan < BmpSource.Width)
36             posX2 = posX2 + span - leftSpan;
37     }
38     // 产生变更后的图片
39     Rectangle cloneRect = new Rectangle(posX1, posY1, posX2 - posX1 + 1, posY2 - posY1 + 1);
40     BmpSource = BmpSource.Clone(cloneRect, BmpSource.PixelFormat);
41 }

 

  第四步骤,在重新取得图片的有效范围后就要将图片进行切割,如上所述一个数字将是一张图片,而此​​切割后的图片将作为之后对照的样本。

01 /// <summary>
02 /// 取得切割后的图
03 /// </summary>
04 /// <param name="pHorizo​​ntalColNumber">int-水平切割数</param>
05 /// <param name="pVerticalRowNumber">int-垂直切割数</param>
06 /// <returns></returns>
07 public Bitmap[] GetSplitPicChars( int pHorizontalColNumber, int pVerticalRowNumber)
08 {
09     if (pHorizontalColNumber == 0 || pVerticalRowNumber == 0)
10         return null ;
11     int avgWidth = BmpSource.Width / pHorizontalColNumber;
12     int avgHeight = BmpSource.Height / pVerticalRowNumber;
13     // 产生存放图片容器阵列
14     Bitmap[] bmpAry = new Bitmap[pHorizontalColNumber * pVerticalRowNumber];
15     // 重新取得数字区域
16     Rectangle cloneRect;
17     for int i = 0; i < pVerticalRowNumber; i++)
18     {
19         for int j = 0; j < pHorizontalColNumber; j++)
20         {
21             cloneRect = new Rectangle(j * avgWidth, i * avgHeight, avgWidth, avgHeight);
22             bmpAry[i * pHorizo​​ntalColNumber + j] = BmpSource.Clone(cloneRect, BmpSource.PixelFormat);
23         }
24     }
25     return bmpAry;
26 }

 

  第五步骤,切割完成图片后就要将数字图片进行二值化,在此就是透过GrayValue 属性指定的值进行区分,如果色彩小于GrayValue 值就是数字,大于GrayValue 值就是背景。

01 /// <summary>
02 /// 取得图片转换后的01编码,0为背景像素1为灰阶像素
03 /// </summary>
04 /// <param name="pBmp">bitmap-单一图片</param>
05 /// <returns></returns>
06 public string GetSingleBmpCode(Bitmap pBmp)
07 {
08     Color color;
09     string code = string .Empty;
10     for int i = 0; i < pBmp.Height; i++)
11         for int j = 0; j < pBmp.Width; j++)
12         {
13             color = pBmp.GetPixel(j, i);
14             if (color.R < GrayValue)
15                 code += "1" ;
16             else
17                 code += "0" ;
18         }
19     return code;
20 }

 

  第六步骤,当连图片都切割好时就剩下要将图片转成二值化编码丢到样本字典里做比对,在此我的样本字典产生方式是先透过以上这些方法,执行程式后于第五步骤时将0 - 9 的二值化编码值先取得,取得后建入样本字典内供之后比对时可以用来对照使用,如比对不到时返回X。

01 /// <summary>
02 /// 取得解码后的验证码字元
03 /// </summary>
04 /// <param name="pSourceCode">string-图片编码</param>
05 /// <returns></returns>
06 public string GetDecChar( string pSourceCode)
07 {
08     string tmpResult = "X" ;
09     for int i = 0; i < DecCodeDictionary.List.Count; i++)
10     {
11         foreach string code in DecCodeDictionary.List[i].Code.ToArray())
12         {
13             int diffCharCount = 0;
14             char [] decChar = code.ToCharArray();
15             char [] sourceChar = pSourceCode.ToCharArray();
16             if (decChar.Length == sourceChar.Length)
17             {
18                 for int j = 0; j < decChar.Length; j++)
19                     if (decChar[j] != sourceChar[j])
20                         diffCharCount++;
21                 if (diffCharCount <= AllowDiffCount)
22                     tmpResult = i.ToString();
23             }
24         }
25     }
26     return tmpResult;
27 }

 

  最后,我们就能够开始进行测试,在一开始WebBrowser 的DocumentCompleted 事件里我呼叫了CaptchaCracked 方法进行破解,方法如下

001 private void CaptchaCracked(Bitmap pBmpImg)
002 {
003     CaptchaCrackedHelper.DecCodeList decCodeList =
004            new CaptchaCrackedHelper.DecCodeList();
005     decCodeList.List.Add( new CaptchaCrackedHelper.DecCodes()    // 0
006     {  
007         Code = new string [] {
008             "001110001001000100110010011001001100100110010011001001000011000" ,
009             "0111100010010001001100100110010011001001100110010010010000111000110000" ,
010             "0111000100100010011001001100100010010011001101100100100001110100100000" }
011     });
012     decCodeList.List.Add( new CaptchaCrackedHelper.DecCodes()    // 1
013     {
014         Code = new string [] {
015             "011100000010000001000000100000010000001000000100000010000111100" ,
016             "011100000010000011000001100000010000011000001100000110000111110" ,
017             "0001100000010000001000000100000011000011000000100000010000001100000000" ,
018             "0000000000110000001000000100000110000001000001100000010000001000001110" }
019     });
020     decCodeList.List.Add( new CaptchaCrackedHelper.DecCodes()    // 2
021     {
022         Code = new string [] {
023             "001100001111000000100000010000000000001000001000000111100111100" ,
024             "0001100001111001000100000010000000000001000001000001111100111100000000" ,
025             "001110001111001001100000010000000000001000001001000111101111100" }
026     });
027     decCodeList.List.Add( new CaptchaCrackedHelper.DecCodes()    // 3
028     {
029         Code = new string [] {
030             "001110001111000000100000110000111000000100000011011001000111000" ,
031             "0011110011110000001000001100001110000001100000100110010001110000000000" ,
032             "" }
033     });
034     decCodeList.List.Add( new CaptchaCrackedHelper.DecCodes()    // 4
035     {
036         Code = new string [] {
037             "000010000011000001100000110000001000001100011111000001000000100" ,
038             "000010000001000001100001110000011000000100011111000011000000100" ,
039             "0001000000100000110000001000000101000110000111100000100000010000000000" ,
040             "0000000000001000001100000110000001000000100000110001111100000100000010" }
041     });
042     decCodeList.List.Add( new CaptchaCrackedHelper.DecCodes()    // 5
043     {
044         Code = new string [] {
045             "001111000111100100000011100001111000000110000001001000000111100" ,
046             "0011110001101000000000111000011011000001100001010010000001111100001000" ,
047             "" }
048     });
049     decCodeList.List.Add( new CaptchaCrackedHelper.DecCodes()    // 6
050     {
051         Code = new string [] {
052             "000011000110000010000011110001001100100110010011001101100011100" ,
053             "0000100001100000100000111100010011001001100100110011011000111000000000" ,
054             "" }
055     });
056     decCodeList.List.Add( new CaptchaCrackedHelper.DecCodes()    // 7
057     {
058         Code = new string [] {
059             "011111001111100000000000010000001000000000000100000010000000000" ,
060             "1111110011011000000000000100000010000000000011000000100000000000000000" ,
061             "" }
062     });
063     decCodeList.List.Add( new CaptchaCrackedHelper.DecCodes()    // 8
064     {
065         Code = new string [] {
066             "001110001000100110010011110000111000100110010011001001100111100" ,
067             "1111000100010011001001111000011000010001001001100100110001110000000000" ,
068             "0000000000111000100100011001001111000011100110011011000100100110001110" ,
069             "0001000000101000100010011101001111000011110010011001001000100110001010" }
070     });
071     decCodeList.List.Add( new CaptchaCrackedHelper.DecCodes()    // 9
072     {
073         Code = new string [] {
074             "001110001001000100110010011001100100011100000010000110000110000" ,
075             "001110001101100100110110011001101100111110000010000111000110000" ,
076             "001110001001000100110010011001101100111110000010000000000000000" ,
077             "0000000101110011001010100110010011001100100011110000010000110000010000" }
078     });
079  
080     CaptchaCrackedHelper cracked = new CaptchaCrackedHelper(pBmpImg, 128, 6, decCodeList);
081  
082     // Step1 灰阶化
083     cracked.ConvertGrayByPixels();
084     picBox2.Image = cracked.BmpSource;
085  
086     // Step2 改变图片范围
087     cracked.ConvertBmpValidRange(5);
088     picBox3.Image = cracked.BmpSource;
089  
090     // Step3 切割图片范围
091     Bitmap[] bitmap = cracked.GetSplitPicChars(5, 1);
092     picBoxP1.Image = bitmap[0];
093     picBoxP2.Image = bitmap[1];
094     picBoxP3.Image = bitmap[2];
095     picBoxP4.Image = bitmap[3];
096     picBoxP5.Image = bitmap[4];
097  
098     txtCodeStr.Text = string .Empty;
099     txtCode.Text = string .Empty;
100     foreach (Bitmap bmp in bitmap)
101     {
102         string result = cracked.GetSingleBmpCode(bmp);
103         txtCodeStr.Text += result + "@" ;
104         txtCode.Text += cracked.GetDecChar(result);
105     }
106  
107 }

 

  以上方法中一开始先建立字典内容,因为这只是简单的范例,所以我直接在开始时候建立字典,当然也可以将字典建立在资料库中,在此的字典样本越多的话比对结果将越准确,字典建立完成后就依照之前所说明的步骤进行处理,经过测试第一种的破解成功率约99%,执行后的结果如下:

 

第二种图形破解

  第一种成功破解后那第二种该如何处理? 第二种验证码加入了噪​​音线干扰,其实针对噪音线我们只需要再多加一个处理方法即可,可以用小画家将图片先撷取出来,用小画家查看噪音线的像素RGB 值是多少,再透过排除方法去除噪音线色彩值区间内的像素点,如下:

01 /// <summary>
02 /// 噪音线处理
03 /// </summary>
04 public void RemoteNoiseLineByPixels()
05 {
06     for int i = 0; i < BmpSource.Height; i++)
07         for int j = 0; j < BmpSource.Width; j++)
08         {
09             int grayValue = BmpSource.GetPixel(j, i).R;
10             if (grayValue <= 255 && grayValue >= 160)
11                 BmpSource.SetPixel(j, i, Color.FromArgb(255, 255, 255));
12         }
13 }

 

  经过测试破解率也有90%以上,执行后的结果如下:

 

第三种图形破解

  而第三种图形跟第二种处理要做的事情一样是要而外加入方法处理,噪音点的处理方式就比较麻烦,因为噪音点可能会跟数字连在一起,而其实只要数字间有相连或干扰判断上都会比较复杂,但是还是能破解,只是手续比较多罢了,在此我只用个判断像素周围是否是白色作为处理方法,其实不太准确,实际上应还需要更多去杂质处理,如下:

01 /// <summary>
02 /// 噪音点处理
03 /// </summary>
04 public void RemoteNoisePointByPixels()
05 {
06     List<NoisePoint> points = new List<NoisePoint>();
07  
08     for int k = 0; k < 5; k++)
09     {
10         for int i = 0; i < BmpSource.Height; i++)
11             for int j = 0; j < BmpSource.Width; j++)
12             {
13                 int flag = 0;
14                 int garyVal = 255;
15                 // 检查上相邻像素
16                 if (i - 1 > 0 && BmpSource.GetPixel(j, i - 1).R != garyVal) flag++;
17                 if (i + 1 < BmpSource.Height && BmpSource.GetPixel(j, i + 1).R != garyVal) flag++;
18                 if (j - 1 > 0 && BmpSource.GetPixel(j - 1, i).R != garyVal) flag++;
19                 if (j + 1 < BmpSource.Width && BmpSource.GetPixel(j + 1, i).R != garyVal) flag++;
20                 if (i - 1 > 0 && j - 1 > 0 && BmpSource.GetPixel(j - 1, i - 1).R != garyVal) flag++;
21                 if (i + 1 < BmpSource.Height && j - 1 > 0 && BmpSource.GetPixel(j - 1, i + 1).R != garyVal) flag++;
22                 if (i - 1 > 0 && j + 1 < BmpSource.Width && BmpSource.GetPixel(j + 1, i - 1).R != garyVal) flag++;
23                 if (i + 1 < BmpSource.Height && j + 1 < BmpSource.Width && BmpSource.GetPixel(j + 1, i + 1).R != garyVal) flag++;
24  
25                 if (flag < 3)
26                     points.Add( new NoisePoint() { X = j, Y = i });
27             }
28         foreach (NoisePoint point in points)
29             BmpSource.SetPixel(point.X, point.Y, Color.FromArgb(255, 255, 255));
30  
31     }
32 }
33  
34 public class NoisePoint
35 {
36     public int X { get set ; }
37     public int Y { get set ; }
38 }

 

  经过测试破解成功率不高...哈哈: P,如果增加字典档样本应该能够再提升成功率,执行结果如下:

 

结论



  以上就是简单图形验证码破解范例,本篇主要的目的在于了解心术不正的人(我?),是使用哪种原理来进行图形验证码的破解,造成机器人攻击的情况发生,正所谓知己知彼,如果知道对方会使用的伎俩的话,相对于我们就能够预先防范,而要能够增加验证码的安全性的话,最好就是将字符连在一起或不规则旋转字符,这样就能够增加破解的困难度,但基本上最后都还是能被破解的。

PS:拿去做坏事不要找我...

 

范例程式码



TCaptchaCracked.rar

 

参考资料



使用PHP对网站验​​证码进行破解

用于验证码图片识别的类(C#源码)

MSHTML Reference

时间: 2024-09-20 00:55:12

[ASP.NET] 图形验证码破解-以简单图形为例的相关文章

图形验证码最佳实践

3次失败之后会要求输入图形验证码 打开两个标签页,都是在有图形验证码的情况下. 第一个标签页成功,第二个标签页输入错误的图形验证码也能通过 为什么? 因为只要操作成功,就不需要校验图形验证码.   今天想设计一个图形验证码的最佳实践 (1) 首先,要明确图形验证码的目的是什么 图形验证码的目的是:防止自动化攻击. 防止暴力破解密码 12306 为什么搞那么复杂的验证码,就是为了防止机器刷票,同时保证是人在操作. 下面是百度"知道"的回答: 图形验证码是验证码的一种.验证码(CAPTCH

图形验证码最佳攻略2

下面是注册 如果是手机用户注册,需要发送短信验证码  说明: 发送图形验证码是为了拦截发送短信的.但是不拦截"注册帐号" 但是,用户体验很别扭,因为图形验证码很显然是错误的,但是却可以注册成功.  如果点击注册帐号 ,也要校验图形验证码,那就让用户输入两次图形验证码,显然不是很人性化 注意:注册时发送短信每次都需要输入图形验证码,而不是发送3次短信才要输入. 那么如何解决这个问题呢? 把注册拆分为两步: 第一步:发送短信验证码     第二步:设置密码和用户名   这样达到的目的: (

python opencv 绘制简单图形

09-python opencv 绘制简单图形 09-python opencv 绘制简单图形 概述 实现过程 引用与创建空图 绘制直线 绘制矩形 绘制圆 绘制椭圆 添加文字 显示图像 源代码 运行结果 参考 概述 本节实现的是使用OpenCV里自带的函数,绘制直线.长方形.圆形和椭圆. 绘制直线 绘制长方形 绘制圆形 绘制椭圆 添加文字 实现过程 引用与创建空图 不再赘述,代码如下. import cv2 import numpy # empty image img = np.zeros((5

自己写的一个图形验证码页面(Asp.Net2.0通过)

asp.net|图形|验证码|页面 项目需要,要在首页登录界面添加一个图形验证码,赶时髦吧,网上一搜,特别多,找了几个,都不太满意.主要问题是大部分代码生成的图片宽度不唯一,页面布局不容易控制,其次是颜色单一,有些又过于抽象,不仔细看很容易弄错.针对特定的客户,我只需要"图片"长宽固定,颜色多样的数字图形验证码,借鉴网上的现有代码,自己操刀完成,以下是效果图: 原理不复杂,就是把网页当画布,运用各色画笔,在特定区域内画出数字,然后以特定格式(本例为PNG格式)发回客户端,在IE中显示为

ASP.NET生成图形验证码的方法详解_实用技巧

本文实例讲述了ASP.NET生成图形验证码的方法.分享给大家供大家参考,具体如下: 通常生成一个图形验证码主要 有3个步骤: (1)随机产生一个长度为N的随机字符串,N的值可由开发可由开发人员自行设置.该字符串可以包含数字.字母等. (2)将随机生成的字符串创建成图片,并显示. (3)保存验证码. 新建一个页面为default.aspx,  放置一个TextBox控件和一个Image控件,TextBox控件用于输入生成的字符串,Image控件用于显示字符串,它的图片就为生成的图形验证码image

使用Asp.Net 2.0编写的图形验证码页面

项目需要,要在首页登录界面添加一个图形验证码,赶时髦吧,网上一搜, 特别多,找了几个,都不太满意.主要问题是大部分代码生成的图片宽度不唯一 ,页面布局不容易控制,其次是颜色单一,有些又过于抽象,不仔细看很容易弄 错.针对特定的客户,我只需要"图片"长宽固定,颜色多样的数字图形验证码 ,借鉴网上的现有代码,自己操刀完成,以下是效果图: 原理不复杂,就是把网页当画布,运用各色画笔,在特定区域内画出数字, 然后以特定格式(本例为PNG格式)发回客户端,在IE中显示为"图片"

.Net Core 下使用ZKWeb.System.Drawing实现验证码功能(图形验证码)_实用技巧

本文介绍.Net Core下用第三方ZKWeb.System.Drawing实现验证码功能. 通过测试的系统: Windows 8.1 64bit Ubuntu Server 16.04 LTS 64bit Fedora 24 64bit CentOS 7.2 64bit 可以实现以下功能: Open jpg, bmp, ico, png Save jpg, bmp, ico, png Resize image Draw graphics with brush and pen Open font

Web 图形验证码的校验1

网站开发中,就会经常涉及到图形验证码的校验,比如: 那么如何校验呢? 我们原来的校验方式:前后端都校验 步骤: (1)前端js 校验图形验证码的MD5 (2)校验通过才真正发送请求到服务器; (3)服务器再次校验图形验证码明文 注意:前端js校验的不是图形验证码明文,而是其MD5值;   如何获取图形验证码的MD5值呢? 服务器需要提供一个单独的接口,返回当前图形验证码的MD5.什么叫"当前"? 就是从session或redis中获取一个图形验证码,而不是重新生成.   后来我们修改了

谷歌图灵测试开发新图形验证码

左边是传统的验证系统,右边的新验证系统则要求用将图形旋转到正确方向 北京时间5月24日上午消息,据国外媒体报道,谷歌研究人员最近正在测试一项新的图形验证码程序,该程序要求用户将随机颠倒的图片调整为正确的方向. 复杂图片识别 非法程序一直在试图利用机器在网站自动注册并实施破坏,但图形验证码程序却可以阻止它们的进入.图形验证码程序一般是几个歪歪斜斜.弯曲的字母和数字,人类可以轻松地辨认并拼写出来,但机器却无法做到.为了帮助网站阻止包括垃圾邮件.滥发文章或帖子以及非法网络投票等行为,这种利用程序自动区