1、為什么要加驗證碼?
因為加了驗證碼可以防御別人攻擊你的網(wǎng)站,舉個例子:別人可以用webbrowser控件做一個模擬瀏覽器,并且模擬提交表單(模擬填寫表單資料和點擊提交按鈕),那么你的服務(wù)器必須接收這些表單傳過來的值,并且做判斷,是否正確。這樣一來,別人可以無限占用你的服務(wù)器資源,而且賬號密碼都不安全,萬一被別人搞個循環(huán)1個1個賬號輪詢的話,很有可能讓別人破解了你的資料信息,所以安全性稍微高點的網(wǎng)站登錄都有彩色圖片驗證碼。
2、為什么彩色驗證碼圖片可以防御別人的攻擊?
因為當(dāng)別人用輪詢技術(shù)模擬登錄的時候,他并不知道你的驗證碼是什么,也獲取不到,因為這是一張圖片,電腦并不能識別里面的數(shù)字是什么(除非破解驗證碼里面的干擾,再利用相關(guān)的圖片識別技術(shù)有可能讀出驗證碼,這里先不扯這個)。讀不出驗證碼就沒有機會輪詢訪問了,當(dāng)然我們后臺判斷的時候一定要先判斷驗證碼是否正確,以防止占用服務(wù)器資源。
3、隨機數(shù) Code
①數(shù)字隨機數(shù)
1 /// <summary>
2 /// 數(shù)字隨機數(shù)
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 }
②字符串隨機數(shù)
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,下標(biāo)從0開始
15 checkCode += VcArray[t];
16 }
17 return checkCode;
18 }
③中文隨機數(shù)
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);//調(diào)用函數(shù)產(chǎn)生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 //根據(jù)漢字編碼的字節(jié)數(shù)組解碼出中文漢字
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 /// 產(chǎn)生隨機中文漢字編碼
23 /// </summary>
24 /// <param name="strlength"></param>
25 /// <returns></returns>
26 private static object[] CreateRegionCode(int strlength)
27 {
28 //定義一個字符串?dāng)?shù)組儲存漢字編碼的組成元素
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 //區(qū)位碼第1位
36 int r1 = rnd.Next(11, 14);
37 string str_r1 = rBase[r1].Trim();
38
39 //區(qū)位碼第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 //區(qū)位碼第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 //區(qū)位碼第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 //定義兩個字節(jié)變量存儲產(chǎn)生的隨機漢字區(qū)位碼
75 byte byte1 = Convert.ToByte(str_r1 + str_r2, 16);
76 byte byte2 = Convert.ToByte(str_r3 + str_r4, 16);
77
78 //將兩個字節(jié)變量存儲在字節(jié)數(shù)組中
79 byte[] str_r = new byte[] { byte1, byte2 };
80
81 //將產(chǎn)生的一個漢字的字節(jié)數(shù)組放入object數(shù)組中
82 bytes.SetValue(str_r, i);
83 }
84 return bytes;
85 }
4、現(xiàn)在有了素材(隨機數(shù)),那么再加上圖片和困擾就完成了彩色圖片驗證碼--困擾背景+圖片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 + stepw));
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);//根據(jù)坐標(biāo)畫線
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、總結(jié)
根據(jù)你要的隨機數(shù)和背景就可以返回BitMap數(shù)組,然后把BitMap數(shù)組以圖片形式存到內(nèi)存流,就可以返回了。在這里只提供思路與制作方法并沒有提供全部代碼與封裝過程,若對代碼有疑問或者需要實例可以加QQ群128584255,大家討論學(xué)習(xí)一下。