MVC Pseudo-12306 Picture Verification Code

Keywords: ASP.NET Session JSON JQuery

The main purpose of this article is to satisfy my curiosity, not to prove something, if it involves any official matters, please let me know thank you. This article will share with you a similar effect that looks like a 12306 picture verification code. This is the last article to share this year's lunar calendar. The landlord will go home by train tomorrow. I wish you all: Happy New Year, everything will go smoothly next year. If you can send me a red envelope, I hope you like it, and I hope you have more "scanner support" and "recommendation" thanks.

 

Display and analysis of effect maps

Algorithms for C # Merging Multiple Pictures and Obtaining Rough Verification Codes for Pictures

How to Use Picture Verification Code in MVC

A Summary of 2016

Prospects for 2017

 

The next step is to share one footprint:

Display and analysis of effect maps

First, let's look at a picture validation code effect address: http://lovexins.com:1001/home/ValidCode And the effect chart:

The above figure is the final example of the pattern, the screenshot of the selected picture on the Internet (such as infringement, please contact the author in time); here looks like the verification code of the railway ticket website, let's first analyze how this authentication code can transfer the information selected by the user to the back end. Take 12306 official website as an example, open the website and check the verification code, lock the corresponding html elements of the authentication code. Then try clicking on an image to see the additional html nodes as shown in the figure:

,

Then we look at the js file corresponding to the login button https://kyfw.12306.cn/otn/resources/merged/login_js.js By searching for the corresponding login button id= "loginSub", we can find its operation to verify the validation code.

Obviously, the selected validation code parameters are passed in through id= "randCode", and then we use this ID to find the corresponding html elements in the html page are:

By comparing the value of the corresponding element here with that of the div generated by our selected button, we can find that the number and value of top are very close, and the left contrast is 3, the top contrast is 16, and the corresponding id= "randCode" is used in the login button js event. So we can boldly guess the hidden text randCode. The value of e corresponds to the matching value of the back-end comparison verification code, which is different from the previous verification code in that it uses coordinates to determine whether the selected verification picture matches, which leads to people's guess about the correctness of the background comparison verification code. The background should be that each small cell picture corresponds to a set of starting and ending coordinates. Only in this way can we judge the correctness of the background comparison verification code. If the picture coordinates selected by the user are included in the allowable range of the small picture in this cell, please correct the process of this conjecture logically. With the conjecture above, we can implement the specific code below. In view of the influence of space, only a few important methods are given below.

 

Algorithms for C # Merging Multiple Pictures and Obtaining Rough Verification Codes for Pictures

Seeing 12306 picture validation code picture, there are many small pictures on each picture, so there are two kinds of conjectures: 1. It is really the staff who processed all the small pictures into a large static real picture; 2. Through the program, many small pictures were merged into a large picture stream; it is not difficult to see that the former would take a lot of work cycles if it was processed (of course, train tickets). So money, maybe that's what I did, who knows? Anyway, I chose the latter to process and merge multiple pictures through the program, so I have the following code:

 1 /// <summary>
 2         /// Generating Verification Code Picture Stream
 3         /// </summary>
 4         /// <param name="imgCode">Cell Picture Collection</param>
 5         /// <param name="width"></param>
 6         /// <param name="height"></param>
 7         /// <returns>Picture flow</returns>
 8         public static byte[] CreateImgCodeStream(ref List<MoImgCode> imgCode, int width = 283, int height = 181)
 9         {
10             var bb = new byte[0];
11             //Initialization Canvas
12             var padding = 1;
13             var lenNum = 2;
14             var len = imgCode.Count;
15             var len_len = len / lenNum;
16             var image = new Bitmap(width, height);
17             var g = Graphics.FromImage(image);
18             try
19             {
20                 var random = new Random();
21                 //Clear the background color
22                 g.Clear(Color.White);
23                 var ii = 1;
24                 var everyX = width / len_len;
25                 var everyY = height / lenNum;
26                 foreach (var item in imgCode)
27                 {
28                     var img = Image.FromFile(item.ImgUrl);
29 
30                     var x2 = everyX * (ii > len_len ? ii - len_len : ii);
31                     var y2 = everyY * (ii > len_len ? 2 : 1) + (ii > len_len ? padding : 0);
32                     //Middle transverse line
33                     if (ii == len_len)
34                     {
35                         g.DrawLine(new Pen(Color.Silver), 0, everyY, width, everyY);
36                     }
37 
38                     var x1 = x2 - everyX + padding;
39                     var y1 = y2 - everyY;
40 
41                     g.DrawImage(img, x1, y1, everyX, everyY);
42 
43                     //Assignment Selection Verification Code Coordinates
44                     if (item.IsChoice)
45                     {
46                         item.Point_A = new Point()
47                         {
48                             X = x1,
49                             Y = y1
50                         };
51                         item.Point_B = new Point
52                         {
53                             X = x1 + everyX,
54                             Y = y1 + everyY
55                         };
56                     }
57 
58                     ii++;
59                 }
60                 //Prospect interference points for drawing pictures
61                 for (int i = 0; i < 100; i++)
62                 {
63                     var x = random.Next(image.Width);
64                     var y = random.Next(image.Height);
65                     image.SetPixel(x, y, Color.FromArgb(random.Next()));
66                 }
67                 //Draw picture borders
68                 g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1);
69 
70                 //Save Image Stream
71                 var stream = new MemoryStream();
72                 image.Save(stream, ImageFormat.Jpeg);
73                 //Output picture stream
74                 bb = stream.ToArray();
75             }
76             catch (Exception ex) { }
77             finally
78             {
79                 g.Dispose();
80                 image.Dispose();
81             }
82             return bb;
83         }

By passing small image sets, and then drawing small pictures into the same big picture through canvas internally, and returning their coordinates corresponding to the big picture (the starting coordinates mentioned above, the terminating coordinates):

From the picture, we can see that each small picture has its own coordinates relative to the origin of the big picture, which is also the basis for us to judge whether the user selected the picture points within the coordinate range of each small picture, so we need to get them by drawing pictures.

Next, it is not enough for us to draw pictures. We also need a method to get random small pictures. My code here is simple, not the best way to get random small pictures for reference. First, we can get the pictures below the program folder.

 1 /// <summary>
 2         /// Initialize the image source
 3         /// </summary>
 4         private static List<MoImgCode> listCode
 5         {
 6             get
 7             {
 8                 var list = new List<MoImgCode>();
 9                 var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "image");
10                 var info = new DirectoryInfo(path);
11                 foreach (var item in info.GetFiles())
12                 {
13                     list.Add(new MoImgCode
14                     {
15                         Index = item.Name,
16                         IndexType = item.Name.Split('_')[0],
17                         ImgUrl = item.FullName
18                     });
19                 }
20                 return list;
21             }
22         }

Method of obtaining random small picture verification code:

 1 /// <summary>
 2         /// Get the Verification Code for Small Pictures
 3         /// </summary>
 4         /// <param name="indexType"></param>
 5         /// <param name="strLen"></param>
 6         /// <returns></returns>
 7         public static List<MoImgCode> CreateImgCode(string indexType, int strLen = 8)
 8         {
 9             var choiceCodeList = new List<MoImgCode>();
10             try
11             {
12                 //Alternative Verification Code
13                 var compareList = new List<MoImgCode>();
14                 var imgCodeLen = listCode.Count;
15 
16                 //Maximum Selected Number 5,Minimum greater than or equal to 1
17                 var maxChoiceNum = 5;
18                 var minChoiceNum = 2;
19                 var rdChoiceNum = rm.Next(minChoiceNum, maxChoiceNum);
20                 //Get the object to be selected
21                 var choiceList = listCode.Where(b => b.IndexType == indexType).Take(rdChoiceNum);
22                 foreach (var item in choiceList)
23                 {
24                     compareList.Add(new MoImgCode
25                     {
26                         Index = item.Index,
27                         ImgUrl = item.ImgUrl,
28                         IndexType = item.IndexType,
29                         IsChoice = true
30                     });
31                 }
32 
33                 //Other remaining options
34                 var lessNum = strLen - choiceList.Count();
35                 //Get other options
36                 for (int i = 0; i < lessNum; i++)
37                 {
38                     var lessCode = listCode.Where(b => !compareList.Any(bb => bb.IndexType == b.IndexType)).ToList();
39                     var val = rm.Next(0, lessCode.Count);
40                     var otherItem = lessCode.Skip(val).Take(1).SingleOrDefault();
41                     compareList.Add(new MoImgCode
42                     {
43                         Index = otherItem.Index,
44                         ImgUrl = otherItem.ImgUrl,
45                         IndexType = otherItem.IndexType,
46                         IsChoice = false
47                     });
48                 }
49 
50                 //Random arrangement
51                 foreach (var item in compareList)
52                 {
53                     var lessCode = compareList.Where(b => !choiceCodeList.Any(bb => bb.Index == b.Index)).ToList();
54 
55                     var comparIndex = rm.Next(0, lessCode.Count);
56                     choiceCodeList.Add(lessCode[comparIndex]);
57                 }
58             }
59             catch (Exception ex)
60             {
61             }
62             return choiceCodeList;
63         }

 

How to Use Picture Verification Code in MVC

Because we need to prompt the user to select the "xxx" type of picture on the page, we need to return the authentication code of the picture and the name of the image type through the background, such as:

Obviously, an action method can't return both the image stream and the text at the same time, so here I separate two methods to return "penguin" and the image respectively. The method code is as follows:

 1   /// <summary>
 2         /// Getting Picture Verification Code Text
 3         /// </summary>
 4         /// <returns></returns>
 5         public JsonResult GetChoiceCode()
 6         {
 7             var data = new Stage.Com.Extend.StageModel.MoData();
 8 
 9             var imgCode = ValidateCode.GetInitImgCode();
10             if (string.IsNullOrWhiteSpace(imgCode.Index)) { data.Msg = "Please refresh the page to get the authentication code"; Json(data); }
11 
12             data.Data = imgCode.IndexType;
13             data.IsOk = true;
14 
15             return Json(data);
16         }
17 
18         /// <summary>
19         /// Get Verification Code Pictures
20         /// </summary>
21         /// <param name="code"></param>
22         /// <returns></returns>
23         public FileResult GetValidateCode06(string code = "Small field")
24         {
25 
26             var imgCode = new List<MoImgCode>();
27             var bb_code = ValidateCode.CreateImgValidateStream(code, ref imgCode, strLen: 8);
28 
29             var choiceList = imgCode.Where(b => b.IsChoice).ToList();
30             var key = "imgCode";
31             if (Session[key] != null)
32             {
33                 Session.Remove(key);
34             }
35             Session.Add(key, JsonConvert.SerializeObject(choiceList));
36 
37             return File(bb_code, "image/jpeg");
38         }

Session.Add (key, JsonConvert.SerializeObject (choiceList) is used in the image method; after obtaining the generated picture authentication code, session is used to save the corresponding coordinates of the authentication code to be matched (the type of authentication code picture that needs to be selected by the user, i.e. the corresponding picture of "penguin"); the user is used to match when submitting the operation button (I am logged in), so the session is used for matching. There are the following coordinate validation codes matching user submissions at login time as follows:

 1   [HttpPost]
 2         public JsonResult UserLogin01(string code)
 3         {
 4             var data = new Stage.Com.Extend.StageModel.MoData();
 5             //Format validation
 6             if (string.IsNullOrWhiteSpace(code)) { data.Msg = "Verification code cannot be empty"; return Json(data); }
 7             if (Session["imgCode"] == null) { data.Msg = "Verification Code Failure"; return Json(data); }
 8             var compareImgCode = JsonConvert.DeserializeObject<List<MoImgCode>>(Session["imgCode"].ToString());
 9             if (compareImgCode.Count<=0) { data.Msg = "Verification code invalid!"; return Json(data); }
10 
11             //Confirmation Verification Code for Contrast Coordinates
12             var codeArr = code.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
13             foreach (var item in codeArr)
14             {
15                 var itemArr = item.Split(':');
16                 if (itemArr.Length != 2) { data.Msg = "Verification code error."; break; }
17 
18                 var x = Convert.ToInt32(itemArr[0]);
19                 var y = Convert.ToInt32(itemArr[1]);
20 
21                 var codeItem = compareImgCode.
22                     Where(b => b.IsChoice).
23                     Where(b =>
24                         (b.Point_B.X > x && b.Point_B.Y > y) &&
25                         (b.Point_A.X < x && b.Point_A.Y < y)).
26                     SingleOrDefault();
27                 if (codeItem == null) { data.Msg = "Verification code error"; break; }
28 
29                 //Verify correctness
30                 codeItem.IsChoice = false;
31             }
32             if (!string.IsNullOrWhiteSpace(data.Msg)) { return Json(data); }
33             //Check if all the validation codes match successfully
34             if (compareImgCode.Any(b => b.IsChoice)) { data.Msg = "Verification code input is incomplete, please try again"; return Json(data); }
35 
36             data.IsOk = true;
37             data.Msg = "Picture Verification Code - Verify success";
38             return Json(data);
39         }

The range of coordinates is used to determine which small picture the user chooses, which is similar to the logic of comparing user input information with session saved verification code information, but image verification code makes some third-party identification software difficult to crack. Here we have to say the nb of the big guys who originally designed this verification code. Next, let's look at the view in mvc. How is the code written?

1  <td>
2                     Please click "<span id="spanCode" style="color:red"></span>",<a style="cursor:pointer" id="a_imgCode">Recovery Verification Code</a><br />
3                     <div id="codeNum" style=" position: relative; cursor: pointer; margin-bottom:30px; margin-top:10px">
4                         <img id="code6" data-src="/home/GetValidateCode06" />
5                     </div>
6 
7                     <button id="btn01" class="btn btn-default">Sign in</button>
8                     <span id="msg01" style="color:red"></span>
9                 </td>

Layout view is just like the screenshot at the beginning of the article. Notice here that the div with id= "codeNum" must be set position: relative. Then I use jquery binding to add a tag click icon to the div if I click on the validation code image. (Here is the image corresponding to the new div background. Note here that these div styles must be position: absol. Otherwise, ute cannot be displayed on the parent div of id= "codeNum". The following is the js code:

 1  //Picture Verification Code Click
 2         $("#code6").on("click", function (e) {
 3 
 4             //Add Selection Button
 5             var container = $("#codeNum");
 6             var x = e.offsetX;
 7             var y = e.offsetY;
 8             container.append('<div class="touclick-hov touclick-bgimg" style="left: ' + x + 'px; top: ' + y + 'px;"></div>');
 9 
10             //Binding Remove Selection Button
11             $("#codeNum div").on("click", function () {
12                 $(this).remove();
13             });
14         });

For our login, if the authentication code fails, then we need to retrieve the authentication code again, or we need to retrieve another authentication code when we can't select the recognized picture. So we have the following js code picture authentication code switch:

 1  //Picture Verification Code Switching 
 2         $("#a_imgCode").on("click", function () {
 3             var img = $("#code6");
 4             var nowTime = new Date().getTime();
 5             //Selection before removal
 6             $("#codeNum div").remove();
 7 
 8             //Get the validation code first
 9             $.post("/home/GetChoiceCode", function (result) {
10                 if (result) {
11                     if (result.IsOk) {
12                         $("#spanCode").html(result.Data);
13                         var src = img.attr("data-src") + "?t=" + nowTime + "&code=" + result.Data;
14                         img.attr("src", src);
15                     } else { console.log("Failed to obtain authentication code."); }
16                 }
17             })
18         });
19         $("#a_imgCode").click();

Then we get the image coordinates of our corresponding clicks in the same way as 12306, and pass them to Acton at the back end for login verification:

 1 //Logon button event
 2         $("#btn01").on("click", function () {
 3 
 4             var msg = $("#msg01");
 5             //Get coordinates
 6             var code = "";
 7             var divs = $("#codeNum div");
 8             for (var i = 0; i < divs.length; i++) {
 9                 var item = $(divs[i]);
10                 code += item.position().left + ":" + item.position().top + "|";
11             }
12             if (code.length <= 0) { msg.html("Please select the Verification Code Picture"); return; }
13             // console.log(code);
14 
15             $.post("/home/UserLogin01", { code: code }, function (result) {
16                 if (result) {
17                     msg.html(result.Msg);
18                     $("#a_imgCode").click();
19                 }
20             });
21         });

Okay, the code for the big show has been released completely. Here's an example of the whole code file package for download. Shenniu-Examples of Verification Codes

 

A Summary of 2016

Study knowledge diligently and happily for everyone

Prospects for 2017

Strive hard to earn some money

Posted by MattMan on Wed, 20 Mar 2019 13:36:28 -0700