亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 擴展 > MVC > 正文

MVC使用極驗驗證制作登錄驗證碼學習筆記7

2024-09-06 20:44:36
字體:
來源:轉載
供稿:網友

       在之前的項目中,如果有需要使用驗證碼,基本都是自己用GDI+畫圖出來,簡單好用,但是卻也存在了一些小問題,首先若較少干擾線,則安全性不是很高,驗證碼容易被機器識別,若多畫太多干擾線條,機器人識別率下降的同時,人眼的識別率也同步下降(震驚哭)。更為重要的是,GDI+繪制的驗證碼一般來說也不會很美觀,如果做一個炫酷的登陸界面卻配了這樣一個驗證碼,畫風詭異,丑到極致。

      再后來瀏覽網頁的過程中,發現很多很多網站項目中都使用了一種叫極驗驗證的驗證碼,采用移動滑塊的方式進行驗證,方便美觀。而一番搜索之后了解到,官方提供的免費版也足以應付我手頭的大多數項目了,不禁想把在MVC學習過程中試著使用極驗驗證來作為登錄的驗證碼。

      極驗官方提供了C#的SDK和Demo供開發者參考,不過是Webform版本的,可讀性不是很高,而現在使用Webform進行網站開發的也基本消失了,我將在官方Webform代碼的基礎上,將其用在ASP.NET MVC程序中。

注冊極驗

到極驗官網注冊賬號之后進入后臺管理界面,點擊添加驗證

添加后我們可以得到ID和KEY

完成驗證邏輯

1. 首先我們需要引入官方的Geetestlib類

using System;using System.Collections;using System.Collections.Generic;using System.Linq;using System.Text;using System.Security.Cryptography;using System.Net;using System.IO;namespace PMS.WebApp.Models{ /// <summary> /// GeetestLib 極驗驗證C# SDK基本庫 /// </summary> public class GeetestLib {  /// <summary>  /// SDK版本號  /// </summary>  public const String version = "3.2.0";  /// <summary>  /// SDK開發語言  /// </summary>  public const String sdkLang = "csharp";  /// <summary>  /// 極驗驗證API URL  /// </summary>  protected const String apiUrl = "http://api.geetest.com";  /// <summary>  /// register url  /// </summary>  protected const String registerUrl = "/register.php";  /// <summary>  /// validate url  /// </summary>  protected const String validateUrl = "/validate.php";  /// <summary>  /// 極驗驗證API服務狀態Session Key  /// </summary>  public const String gtServerStatusSessionKey = "gt_server_status";  /// <summary>  /// 極驗驗證二次驗證表單數據 Chllenge  /// </summary>  public const String fnGeetestChallenge = "geetest_challenge";  /// <summary>  /// 極驗驗證二次驗證表單數據 Validate  /// </summary>  public const String fnGeetestValidate = "geetest_validate";  /// <summary>  /// 極驗驗證二次驗證表單數據 Seccode  /// </summary>  public const String fnGeetestSeccode = "geetest_seccode";  private String userID = "";  private String responseStr = "";  private String captchaID = "";  private String privateKey = "";  /// <summary>  /// 驗證成功結果字符串  /// </summary>  public const int successResult = 1;  /// <summary>  /// 證結失敗驗果字符串  /// </summary>  public const int failResult = 0;  /// <summary>  /// 判定為機器人結果字符串  /// </summary>  public const String forbiddenResult = "forbidden";  /// <summary>  /// GeetestLib構造函數  /// </summary>  /// <param name="publicKey">極驗驗證公鑰</param>  /// <param name="privateKey">極驗驗證私鑰</param>  public GeetestLib(String publicKey, String privateKey)  {   this.privateKey = privateKey;   this.captchaID = publicKey;  }  private int getRandomNum()  {   Random rand =new Random();   int randRes = rand.Next(100);   return randRes;  }  /// <summary>  /// 驗證初始化預處理  /// </summary>  /// <returns>初始化結果</returns>  public Byte preProcess()  {   if (this.captchaID == null)   {    Console.WriteLine("publicKey is null!");   }   else   {    String challenge = this.registerChallenge();    if (challenge.Length == 32)    {     this.getSuccessPreProcessRes(challenge);     return 1;    }    else    {     this.getFailPreProcessRes();     Console.WriteLine("Server regist challenge failed!");    }   }   return 0;  }  public Byte preProcess(String userID)  {   if (this.captchaID == null)   {    Console.WriteLine("publicKey is null!");   }   else   {    this.userID = userID;    String challenge = this.registerChallenge();    if (challenge.Length == 32)    {     this.getSuccessPreProcessRes(challenge);     return 1;    }    else    {     this.getFailPreProcessRes();     Console.WriteLine("Server regist challenge failed!");    }   }   return 0;  }  public String getResponseStr()  {   return this.responseStr;  }  /// <summary>  /// 預處理失敗后的返回格式串  /// </summary>  private void getFailPreProcessRes()  {   int rand1 = this.getRandomNum();   int rand2 = this.getRandomNum();   String md5Str1 = this.md5Encode(rand1 + "");   String md5Str2 = this.md5Encode(rand2 + "");   String challenge = md5Str1 + md5Str2.Substring(0, 2);   this.responseStr = "{" + string.Format(     "/"success/":{0},/"gt/":/"{1}/",/"challenge/":/"{2}/"", 0,    this.captchaID, challenge) + "}";  }  /// <summary>  /// 預處理成功后的標準串  /// </summary>  private void getSuccessPreProcessRes(String challenge)  {   challenge = this.md5Encode(challenge + this.privateKey);   this.responseStr ="{" + string.Format(    "/"success/":{0},/"gt/":/"{1}/",/"challenge/":/"{2}/"", 1,     this.captchaID, challenge) + "}";  }  /// <summary>  /// failback模式的驗證方式  /// </summary>  /// <param name="challenge">failback模式下用于與validate一起解碼答案, 判斷驗證是否正確</param>  /// <param name="validate">failback模式下用于與challenge一起解碼答案, 判斷驗證是否正確</param>  /// <param name="seccode">failback模式下,其實是個沒用的參數</param>  /// <returns>驗證結果</returns>  public int failbackValidateRequest(String challenge, String validate, String seccode)  {   if (!this.requestIsLegal(challenge, validate, seccode)) return GeetestLib.failResult;   String[] validateStr = validate.Split('_');   String encodeAns = validateStr[0];   String encodeFullBgImgIndex = validateStr[1];   String encodeImgGrpIndex = validateStr[2];   int decodeAns = this.decodeResponse(challenge, encodeAns);   int decodeFullBgImgIndex = this.decodeResponse(challenge, encodeFullBgImgIndex);   int decodeImgGrpIndex = this.decodeResponse(challenge, encodeImgGrpIndex);   int validateResult = this.validateFailImage(decodeAns, decodeFullBgImgIndex, decodeImgGrpIndex);   return validateResult;  }  private int validateFailImage(int ans, int full_bg_index, int img_grp_index)  {   const int thread = 3;   String full_bg_name = this.md5Encode(full_bg_index + "").Substring(0, 10);   String bg_name = md5Encode(img_grp_index + "").Substring(10, 10);   String answer_decode = "";   for (int i = 0;i < 9; i++)   {    if (i % 2 == 0) answer_decode += full_bg_name.ElementAt(i);    else if (i % 2 == 1) answer_decode += bg_name.ElementAt(i);   }   String x_decode = answer_decode.Substring(4);   int x_int = Convert.ToInt32(x_decode, 16);   int result = x_int % 200;   if (result < 40) result = 40;   if (Math.Abs(ans - result) < thread) return GeetestLib.successResult;   else return GeetestLib.failResult;  }  private Boolean requestIsLegal(String challenge, String validate, String seccode)  {   if (challenge.Equals(string.Empty) || validate.Equals(string.Empty) || seccode.Equals(string.Empty)) return false;   return true;  }  /// <summary>  /// 向gt-server進行二次驗證  /// </summary>  /// <param name="challenge">本次驗證會話的唯一標識</param>  /// <param name="validate">拖動完成后server端返回的驗證結果標識字符串</param>  /// <param name="seccode">驗證結果的校驗碼,如果gt-server返回的不與這個值相等則表明驗證失敗</param>  /// <returns>二次驗證結果</returns>  public int enhencedValidateRequest(String challenge, String validate, String seccode)  {   if (!this.requestIsLegal(challenge, validate, seccode)) return GeetestLib.failResult;   if (validate.Length > 0 && checkResultByPrivate(challenge, validate))   {    String query = "seccode=" + seccode + "&sdk=csharp_" + GeetestLib.version;    String response = "";    try    {     response = postValidate(query);    }    catch (Exception e)    {     Console.WriteLine(e);    }    if (response.Equals(md5Encode(seccode)))    {     return GeetestLib.successResult;    }   }   return GeetestLib.failResult;  }  public int enhencedValidateRequest(String challenge, String validate, String seccode, String userID)  {   if (!this.requestIsLegal(challenge, validate, seccode)) return GeetestLib.failResult;   if (validate.Length > 0 && checkResultByPrivate(challenge, validate))   {    String query = "seccode=" + seccode + "&user_id=" + userID + "&sdk=csharp_" + GeetestLib.version;    String response = "";    try    {     response = postValidate(query);    }    catch (Exception e)    {     Console.WriteLine(e);    }    if (response.Equals(md5Encode(seccode)))    {     return GeetestLib.successResult;    }   }   return GeetestLib.failResult;  }  private String readContentFromGet(String url)  {   try   {    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);    request.Timeout = 20000;    HttpWebResponse response = (HttpWebResponse)request.GetResponse();    Stream myResponseStream = response.GetResponseStream();    StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));    String retString = myStreamReader.ReadToEnd();    myStreamReader.Close();    myResponseStream.Close();    return retString;   }   catch   {    return "";     }  }  private String registerChallenge()  {   String url = "";   if (string.Empty.Equals(this.userID))   {    url = string.Format("{0}{1}?gt={2}", GeetestLib.apiUrl, GeetestLib.registerUrl, this.captchaID);   }   else   {    url = string.Format("{0}{1}?gt={2}&user_id={3}", GeetestLib.apiUrl, GeetestLib.registerUrl, this.captchaID, this.userID);   }   string retString = this.readContentFromGet(url);   return retString;  }  private Boolean checkResultByPrivate(String origin, String validate)  {   String encodeStr = md5Encode(privateKey + "geetest" + origin);   return validate.Equals(encodeStr);  }  private String postValidate(String data)  {   String url = string.Format("{0}{1}", GeetestLib.apiUrl, GeetestLib.validateUrl);   HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);   request.Method = "POST";   request.ContentType = "application/x-www-form-urlencoded";   request.ContentLength = Encoding.UTF8.GetByteCount(data);   // 發送數據   Stream myRequestStream = request.GetRequestStream();   byte[] requestBytes = System.Text.Encoding.ASCII.GetBytes(data);   myRequestStream.Write(requestBytes, 0, requestBytes.Length);   myRequestStream.Close();   HttpWebResponse response = (HttpWebResponse)request.GetResponse();   // 讀取返回信息   Stream myResponseStream = response.GetResponseStream();   StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));   string retString = myStreamReader.ReadToEnd();   myStreamReader.Close();   myResponseStream.Close();   return retString;  }  private int decodeRandBase(String challenge)  {   String baseStr = challenge.Substring(32, 2);   List<int> tempList = new List<int>();   for(int i = 0; i < baseStr.Length; i++)   {    int tempAscii = (int)baseStr[i];    tempList.Add((tempAscii > 57) ? (tempAscii - 87)     : (tempAscii - 48));   }   int result = tempList.ElementAt(0) * 36 + tempList.ElementAt(1);   return result;  }  private int decodeResponse(String challenge, String str)  {   if (str.Length>100) return 0;   int[] shuzi = new int[] { 1, 2, 5, 10, 50};   String chongfu = "";   Hashtable key = new Hashtable();   int count = 0;   for (int i=0;i<challenge.Length;i++)   {    String item = challenge.ElementAt(i) + "";    if (chongfu.Contains(item)) continue;    else    {     int value = shuzi[count % 5];     chongfu += item;     count++;     key.Add(item, value);    }   }   int res = 0;   for (int i = 0; i < str.Length; i++) res += (int)key[str[i]+""];   res = res - this.decodeRandBase(challenge);   return res;  }  private String md5Encode(String plainText)  {   MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();   string t2 = BitConverter.ToString(md5.ComputeHash(UTF8Encoding.Default.GetBytes(plainText)));   t2 = t2.Replace("-", "");   t2 = t2.ToLower();   return t2;  } }}            
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲人在线观看| 久久影院免费观看| 国产精品999999| 懂色aⅴ精品一区二区三区蜜月| 国产成人97精品免费看片| 97超级碰在线看视频免费在线看| 欧美激情第一页xxx| 18一19gay欧美视频网站| 懂色aⅴ精品一区二区三区蜜月| 中文字幕无线精品亚洲乱码一区| 欧美极品少妇全裸体| 91精品国产自产在线老师啪| 国产精品老女人精品视频| 国产精品亚洲美女av网站| 亚洲男人天堂网| 国产亚洲精品久久久久久牛牛| 欧美日韩亚洲一区二区三区| 久久99热精品这里久久精品| 青青草一区二区| 青青草国产精品一区二区| 亚洲国产中文字幕在线观看| 欧美精品videofree1080p| 精品中文字幕视频| 国产成人精品优优av| 久久久久北条麻妃免费看| 久久久久久久999精品视频| 亚洲国模精品私拍| 久久影院资源站| 亚洲欧美日韩在线一区| 日韩在线视频网站| 91av在线免费观看视频| 欧美限制级电影在线观看| 欧美成人激情图片网| 国产在线拍偷自揄拍精品| 欧美在线亚洲一区| 亚洲一区二区三区成人在线视频精品| 亚洲一区二区三区四区在线播放| 亚洲欧美在线一区二区| 中文字幕无线精品亚洲乱码一区| 久久久www成人免费精品张筱雨| 亚洲男人天堂手机在线| 成人亚洲欧美一区二区三区| 欧美成人免费全部观看天天性色| 日韩精品在线影院| 久久久免费电影| 亚洲天堂色网站| 国产精品一区二区三区久久| 亚洲视频在线免费观看| 国产一区二区欧美日韩| 欧美重口另类videos人妖| 欧美性jizz18性欧美| 成人福利视频网| 在线观看国产成人av片| 国产精品夜色7777狼人| 亚洲午夜精品久久久久久久久久久久| 国产精品亚洲一区二区三区| 国产精选久久久久久| 国产精品美腿一区在线看| 日韩在线观看成人| 久热精品在线视频| 欧美国产精品日韩| 欧美午夜女人视频在线| 中文综合在线观看| 日韩第一页在线| 欧美中文在线字幕| 综合激情国产一区| 欧美精品国产精品日韩精品| 在线色欧美三级视频| 4438全国成人免费| 亚洲精品aⅴ中文字幕乱码| 91中文字幕在线观看| 中文字幕日本欧美| 性欧美xxxx| 色妞一区二区三区| 欧美国产日韩一区二区| 午夜精品一区二区三区视频免费看| 欧美高清自拍一区| 国产精品嫩草影院久久久| 中文字幕精品一区二区精品| 日韩美女免费视频| 黑人巨大精品欧美一区二区免费| 国产不卡在线观看| 欧美精品videofree1080p| 久久69精品久久久久久久电影好| 国产精品video| 欧美日韩中文字幕在线视频| 亚洲区中文字幕| 亚洲网站在线观看| 国产精品美女久久| 精品亚洲一区二区三区| 国产日韩精品一区二区| 日韩免费观看在线观看| 国产精品都在这里| 国产精品69久久| 亚洲人成电影在线观看天堂色| 国产精品视频自拍| 欧美日韩亚洲一区二| 在线精品高清中文字幕| 亚洲男人天堂九九视频| 亚洲精品美女免费| 中文字幕亚洲欧美日韩在线不卡| 日韩中文理论片| 久久99精品国产99久久6尤物| 国产成人精品视频| 国产乱肥老妇国产一区二| 成人福利在线视频| www.日韩免费| 热门国产精品亚洲第一区在线| 日韩欧美极品在线观看| 久久精品一区中文字幕| 成人国产精品色哟哟| 欧美肥老太性生活视频| 91在线国产电影| 日韩成人在线视频网站| 国产精品亚洲自拍| 国内精品中文字幕| 国产97在线|日韩| 欧美国产乱视频| 亚洲电影免费在线观看| 国产精品中文在线| 俺去了亚洲欧美日韩| 亚洲性生活视频在线观看| 久久人人爽人人爽人人片av高清| 欧美电影在线观看网站| 色综合色综合网色综合| 国产精品久久久久久久久久| 美女久久久久久久| 92裸体在线视频网站| 亚洲一区二区三区乱码aⅴ蜜桃女| 在线激情影院一区| 久久人人爽人人爽人人片av高清| 久久久av亚洲男天堂| 国产在线观看91精品一区| 欧美日韩加勒比精品一区| 久久中国妇女中文字幕| 日韩欧美国产网站| 97热在线精品视频在线观看| 97精品久久久| 久久久久久久久久久成人| 久久精品视频播放| 欧美日韩综合视频网址| 日韩欧美大尺度| 久久99热精品这里久久精品| 精品呦交小u女在线| 成人日韩av在线| 一本色道久久88综合亚洲精品ⅰ| 亚洲精品av在线播放| 国模视频一区二区三区| 在线亚洲午夜片av大片| 欧美日韩xxxxx| 国产亚洲精品高潮| 国产欧美婷婷中文| 日韩欧美第一页| 黄色精品在线看| 国产精品久久电影观看| 最近2019中文字幕在线高清| 精品少妇一区二区30p| 日本久久精品视频| 久久久久国色av免费观看性色| 久久精品中文字幕一区| 国产精品男女猛烈高潮激情| 69**夜色精品国产69乱| 国产精品99久久久久久久久| 国产www精品|