現在驗證碼的形式越來越豐富,今天要實現的是在點擊圖片中的文字來進行校驗的驗證碼,如圖
這種驗證碼驗證是驗證鼠標是否選中了圖片中文字的位置,以及選擇的順序,產生驗證碼的時候可以提供一組底圖,然后隨機獲取一張圖片,隨機選取幾個字,然后把文字的順序打亂,分別隨機放到圖片的一個位置上,然后記錄文字的位置和順序,驗證的時候驗證一下文字的位置和順序即可
驗證碼圖片的類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
/// <summary> /// 二維碼圖片 /// </summary> public class VerCodePic { /// <summary> /// 圖片鏈接 /// </summary> public string PicURL { get ; set ; } /// <summary> /// 第一個字位置 /// </summary> public FontPoint Font1 { get ; set ; } /// <summary> /// 第二個字位置 /// </summary> public FontPoint Font2 { get ; set ; } /// <summary> /// 第三個字位置 /// </summary> public FontPoint Font3 { get ; set ; } /// <summary> /// 第四個字位置 /// </summary> public FontPoint Font4 { get ; set ; } } /// <summary> /// 文字位置 /// </summary> public class FontPoint { public int X { get ; set ; } public int Y { get ; set ; } } |
生成驗證碼圖片驗證碼的方法,在這個方法中指定了生成的驗證碼圖片中字體大小為20個像素,因為驗證碼底圖的大小是固定的,所以就把驗證碼底圖按照字體的大小分成了若干個網格位置,指定一個文字在圖片中的位置時只需要隨機獲取其中一個網格即可,如果這個網格中沒有指定過文字,那就把文字放到這個網格中。
提前設定網格的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
private static ArrayList _FontPoint; public static ArrayList FontPoint { get { if (_FontPoint== null ) { _FontPoint = new ArrayList(); for ( int x=0;x<10;x++) { for ( int y=0;y<5;y++) { _FontPoint.Add( new Models.FontPoint() { X = x * 28, Y = y * 20 }); } } } return _FontPoint; } } |
我選定的驗證碼底圖為280*100的,所以按照上邊的方法將圖片分成了若干個網格,在下邊設定一個文字位置的時候隨機選取其中一個位置,而且給每個字都設定了不一樣的顏色
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
/// <summary> /// 根據文字和圖片獲取驗證碼圖片 /// </summary> /// <param name="content"></param> /// <param name="picFileName"></param> /// <returns></returns> public static VerCodePic GetVerCodePic( string content, string picFileName, int fontSize=20) { ClassLoger.Info( "FileHelper.GetVerCodePic" , "開始生成二維碼" ); Bitmap bmp = new Bitmap(picFileName); List< int > hlist = new List< int >(); VerCodePic codepic = new VerCodePic(); int i = Utils.GetRandom(0, SystemSet.FontPoint.Count - 1); codepic.Font1 = SystemSet.FontPoint[i] as FontPoint; hlist.Add(i); A: int i2 = Utils.GetRandom(0, SystemSet.FontPoint.Count - 1); if (hlist.Contains(i2)) goto A; codepic.Font2 = SystemSet.FontPoint[i2] as FontPoint; hlist.Add(i2); B: int i3 = Utils.GetRandom(0, SystemSet.FontPoint.Count - 1); if (hlist.Contains(i3)) goto B; hlist.Add(i3); codepic.Font3 = SystemSet.FontPoint[i3] as FontPoint; C: int i4 = Utils.GetRandom(0, SystemSet.FontPoint.Count - 1); if (hlist.Contains(i4)) goto C; hlist.Add(i4); codepic.Font4 = SystemSet.FontPoint[i4] as FontPoint; string fileName = (content + "-" + picFileName+ "-" +i+ "|" +i2+ "|" +i3+ "|" +i4).MD5()+Path.GetExtension(picFileName); string dir = Path.Combine(SystemSet.ResourcesPath, SystemSet.VerCodePicPath); string filePath = Path.Combine(dir, fileName); if (File.Exists(filePath)) { codepic.PicURL = string .Format( "{0}/{1}/{2}" , SystemSet.WebResourcesSite, SystemSet.VerCodePicPath, fileName); return codepic; } if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } Graphics g = Graphics.FromImage(bmp); Font font = new Font( "微軟雅黑" , fontSize, GraphicsUnit.Pixel); SolidBrush sbrush = new SolidBrush(Color.Black); SolidBrush sbrush1 = new SolidBrush(Color.Peru); SolidBrush sbrush2 = new SolidBrush(Color.YellowGreen); SolidBrush sbrush3 = new SolidBrush(Color.SkyBlue); List< char > fontlist = content.ToList(); ClassLoger.Info( "FileHelper.GetVerCodePic" , fontlist.Count.ToString()); g.DrawString(fontlist[0].TryToString(), font, sbrush, new PointF(codepic.Font1.X, codepic.Font1.Y)); g.DrawString(fontlist[1].TryToString(), font, sbrush1, new PointF(codepic.Font2.X, codepic.Font2.Y)); g.DrawString(fontlist[2].TryToString(), font, sbrush2, new PointF(codepic.Font3.X, codepic.Font3.Y)); g.DrawString(fontlist[3].TryToString(), font, sbrush3, new PointF(codepic.Font4.X, codepic.Font4.Y)); bmp.Save(filePath, ImageFormat.Jpeg); codepic.PicURL = string .Format( "{0}/{1}/{2}" ,SystemSet.WebResourcesSite, SystemSet.VerCodePicPath, fileName); return codepic; } |
獲取圖片驗證碼的api接口,在這個接口中從成語庫中隨機選取了一個成語,然后隨機選取了一個圖片,然后調用生成圖片驗證碼的方法,生成了圖片驗證碼,并且把驗證碼對應的信息緩存在redis中,設定緩存時間,將redis的key作為一個臨時令牌隨同驗證碼返回
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
/// <summary> /// 獲取驗證碼,有效時間10分鐘 /// </summary> /// <returns></returns> [HttpGet] [Route( "vercode" )] public JsonResult<VerCodePicViewModel> VerCodePic() { JsonResult<VerCodePicViewModel> result = new JsonResult<VerCodePicViewModel>(); result.code = 1; result.msg = "OK" ; try { ClassLoger.Info( "VerCodePic" , "開始獲取成語" ); cy_dictBll cybll = new cy_dictBll(); IList<cy_dict> cylist = cybll.GetAllcy_dict(); ClassLoger.Info( "VerCodePic" , cylist.Count.ToString()); int i = Utils.GetRandom(0, cylist.Count-1); ClassLoger.Info( "VerCodePic" ,i.ToString()); cy_dict cy = cylist[i]; ClassLoger.Info( "VerCodePic成語:" ,cy.chengyu); VerCodePicViewModel vcvm = new VerCodePicViewModel(); string sourcePic = FileHelper.GetVerCodePicResource(); if (sourcePic.IsNull() || !File.Exists(sourcePic)) { sourcePic = @"E:\WebResources\images\VerCodePicSource\1.jpg" ; } ClassLoger.Info( "VerCodePic圖片" ,sourcePic); VerCodePic codepic = FileHelper.GetVerCodePic(cy.chengyu, sourcePic); vcvm.content = cy.chengyu; vcvm.MainPic = codepic.PicURL; result.Result = vcvm; string key = cookieKey(); RedisBase.Item_Set(key, codepic); RedisBase.ExpireEntryAt(key,DateTime.Now.AddMinutes(10)); result.ResultMsg = key; } catch (Exception ex) { ClassLoger.Error( "AccountController.VerCodePic" ,ex); result.code = -1; result.msg = "AccountController.VerCodePic發生異常:" +ex.Message; } return result; } |
效果如圖:
圖片驗證碼校驗接口參數結構
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public class CheckPicCodeViewModel { /// <summary> /// 客戶端令牌 /// </summary> public string token { get ; set ; } public double x1 { get ; set ; } public double x2 { get ; set ; } public double x3 { get ; set ; } public double x4 { get ; set ; } public double y1 { get ; set ; } public double y2 { get ; set ; } public double y3 { get ; set ; } public double y4 { get ; set ; } } |
驗證碼校驗接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
/// <summary> /// 校驗圖片驗證碼是否正確 /// </summary> /// <param name="piccode"></param> /// <returns></returns> [HttpPost] [Route( "checkpiccode" )] public async Task<IHttpActionResult> CheckPicCode([FromBody]CheckPicCodeViewModel piccode) { JsonResult< bool > result = new JsonResult< bool >(); result.code = 1; result.msg = "OK" ; if (piccode == null ) { result.Result = false ; result.ResultMsg = "參數錯誤" ; return Ok(result); } if ( string .IsNullOrEmpty(piccode.token) || !RedisBase.ContainsKey(piccode.token)) { result.Result = false ; result.ResultMsg = "驗證碼已過期" ; return Ok(result); } result.Result = await Task.Run< bool >(() => { bool flag = false ; VerCodePic codepic = RedisBase.Item_Get<VerCodePic>(piccode.token); if (Math.Abs(codepic.Font1.X - piccode.x1) > 0.5 || Math.Abs(codepic.Font1.Y - piccode.y1) > 0.5 || Math.Abs(codepic.Font2.X - piccode.x2) > 0.5 || Math.Abs(codepic.Font2.Y - piccode.y2) > 0.5 || Math.Abs(codepic.Font3.X - piccode.x3) > 0.5 || Math.Abs(codepic.Font3.Y - piccode.y3) > 0.5 || Math.Abs(codepic.Font4.X - piccode.x4) > 0.5 || Math.Abs(codepic.Font4.Y - piccode.y4) > 0.5) { flag = false ; result.ResultMsg = "驗證碼錯誤" ; } else { flag = true ; result.ResultMsg = "驗證碼正確" ; } return flag; }); return Ok(result); } |
傳入用戶選中的位置和順序,并對其進行驗證。
以上所述是小編給大家介紹的Asp.net Web Api實現圖片點擊式圖片驗證碼,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!
原文鏈接:http://www.cnblogs.com/liemei/p/7060831.html