[ASP.NET MVC] 使用 Google reCAPTCHA 圖像、圖形驗證(我不是機器人)

[ASP.NET MVC] 使用 Google reCAPTCHA 圖像、圖形驗證(我不是機器人)

前言:

 

常常看到些網站在登入時或者在需要比較安全操作(銀行轉帳)的時候,都會需要填入辨識圖形上所出現的文字或數字,目的是要辨別是 "真人" 在操作,避免有心人士做惡意的攻擊。比較常見的就是使用機器人重複嘗試登入密碼(暴力破解),所以才會有圖形驗證的產生。以下常見的圖形驗證:

 

滑鼠點擊位置辨識:

image

純數字:

image

 

文字數字線條干擾:

image

 

不過現在影像辨識技術已經非常發達了以上這些方法都是蠻容易就可以輕易繞過,
甚至有些連人都辨別不太出來的機器都可以辨別.....

image

 

 

之後 Google reCAPTCHA 就改變成以下的方式,背後原理不太清楚,
不過大致上可以猜測應該是預估你的滑鼠行為或者是停留時間來判斷等等…

image

 

利用圖形選擇方式也比較人性化XD

image

 

 

如何使用:


先到 Google reCAPTCHA 註冊基本資訊,取得API KEY:

image

 

這邊要注意網域名稱要設定正確,否則當 reCAPTCHA 辨別到你的網址不是你所設定的網域就會出現以下錯誤訊息:

image

 

註冊完後會得到以下資訊:

  • 私鑰:後端驗證用
  • reCAPTCHA 的JavaScript檔案:放到</head>結尾前
  • <div….:圖形驗證的程式碼,放到網頁中你想呈現的位置上

image

 

介紹兩種方式:

  • 使用別人寫好的,NuGet 搜尋 "GoogleRecaptcha"
  • 自己寫

 

使用 GoogleRecaptcha

  1. 專案右鍵 > Manage NuGet Packages
  2. 搜尋 GoogleRecaptcha、GoogleRecaptchaMvc(兩個都要裝)
  3. 安裝

image

 

 

GoogleRecaptchaMvc 是可以在Razor 中使用 RecaptchaV2 方法,參數為註冊時的 SiteKey:

   1: @Html.RecaptchaV2("6LdQaxATAAAAAB7UuxNH4lIoC_0wcJE3scx-QJ5v")

 

記得要引用 reCAPTCHA 的 js 完整如下:

   1: @using GoogleRecaptchaMvc
   2: <!DOCTYPE html>

		
		
   3:  

		
		
   4: <html>

		
		
   5: <head>

		
		
   6:     <title>GoogleRecaptcha</title>

		
		
   7:     <script src='https://www.google.com/recaptcha/api.js'></script>

		
		
   8: </head>

		
		
   9: <body>

		
		
  10:     @using (Html.BeginForm("Index", "Home", FormMethod.Post))

		
		
  11:     {

		
		
  12:         <div>

		
		
  13:             @Html.RecaptchaV2("6LdQaxATAAAAAB7UuxNH4lIoC_0wcJE3scx-QJ5v")

		
		
  14:         </div>

		
		
  15:     }

		
		
  16: </body>

		
		
  17: </html>

 

前端部分就已經完成了,夠簡單吧XD

image

 

去看 GoogleRecaptchaMvc 的 RecaptchaV2 擴充方法其實就是幫你組合起來:

   1: public static IHtmlString RecaptchaV2(this HtmlHelper helper, string siteKey)
   2:         {

		
		
   3:             var htmlString = String.Format("<div class='g-recaptcha' data-sitekey='{0}'></div>", siteKey);

		
		
   4:             return new HtmlString(htmlString);

		
		
   5:         }

 

接下來處理後端(以下節錄自官網的 Demo Code):

image

   1: using System.Web.Mvc;
   2: using GoogleRecaptcha;

		
		
   3:  

		
		
   4: namespace Google.reCaptcha.WEB.Controllers

		
		
   5: {

		
		
   6:     public class HomeController : Controller

		
		
   7:     {

		
		
   8:         // GET: Home

		
		
   9:         public ActionResult Index()

		
		
  10:         {

		
		
  11:             return View();

		
		
  12:         }

		
		
  13:  

		
		
  14:         [HttpPost]

		
		
  15:         public ActionResult Index(FormCollection form)

		
		
  16:         {

		
		
  17:             IRecaptcha<RecaptchaV2Result> recaptcha = new RecaptchaV2(new RecaptchaV2Data(){

		
		
  18:                 Secret = "6LdQaxATAAAAACWOZDLB5C06RfW_0qhXJYagQ9iF"

		
		
  19:             });

		
		
  20:  

		
		
  21:             // Verify the captcha

		
		
  22:             var result = recaptcha.Verify();

		
		
  23:             if (result.Success) // Success!!!

		
		
  24:             {

		
		
  25:                 //TODO: write code here

		
		
  26:             }

		
		
  27:             return View();

		
		
  28:         }

		
		
  29:     }

		
		
  30: }

Secret 帶入當初註冊的私鑰,接下來就是用 Verify() 方法看回傳是不是 true 或 false 來判斷。

 

這邊可能會發現,诶? 他沒有從 from 物件抓取前端傳回來的 token 怎麼驗證?

其實他在 new RecaptchaV2Data() 的時候就抓取了前端的 Form["g-recaptcha-response"]欄位,

所以在使用上就變得更簡單了。

 

自己寫

前端部分:

  1. 先引用reCAPTCHA的JS (6行)
  2. 放入要呈現的位置(10行)
   1: <!DOCTYPE html>
   2:  

		
		
   3: <html>

		
		
   4: <head>

		
		
   5:     <title>title</title>

		
		
   6:     <script src='https://www.google.com/recaptcha/api.js'></script>

		
		
   7: </head>

		
		
   8: <body>

		
		
   9: <div>

		
		
  10:     <div class="g-recaptcha" data-sitekey="6LdQaxATAAAAAB7UuxNH4lIoC_0wcJE3scx-QJ5v"></div>

		
		
  11: </div>

		
		
  12: </body>

		
		
  13: </html>

	

 

 

前端完成:

image

 

後端部分:

可以先看 官方文件API 文件

image

 

接下來我們實作一個類別 GoogleReCaptcha:

  • 組合POST Parameter
  • 發送Request
  • 取回結果

image

   1: public class GoogleReCaptcha
   2:     {

		
		
   3:         public bool Success { get; set; }

		
		
   4:         public bool GetCaptchaResponse(string message)

		
		
   5:         {

		
		
   6:             try

		
		
   7:             {

		
		
   8:                 using (var client = new HttpClient())

		
		
   9:                 {

		
		
  10:                     var content = new FormUrlEncodedContent(new[]{

		
		
  11:                     new KeyValuePair<string, string>("secret", "{YourSecretKey}"),

		
		
  12:                     new KeyValuePair<string, string>("response", message),

		
		
  13:                 });

		
		
  14:  

		
		
  15:                     var result = client.PostAsync("https://www.google.com/recaptcha/api/siteverify", content).Result;

		
		
  16:                     var resultContent = result.Content.ReadAsStringAsync().Result;

		
		
  17:                     var data = JsonConvert.DeserializeObject<GoogleReCaptcha>(resultContent);

		
		
  18:                     return data.Success;

		
		
  19:                 }

		
		
  20:             }

		
		
  21:             catch{return false;}

		
		
  22:         }

		
		
  23:     }

 

使用 GoogleReCaptcha :

  • 帶入前端傳來的token
  • 會回傳 ture 或 false

image

 

另外其實在 Google API 文件中還有提到回傳錯誤的 error code 的說明,這部分就沒有針對此實作了。

image

 

專案範例以上傳 GitHub 有興趣的可以自行嘗試看看。

 

 

 

 

 

 

 

 


如有錯誤還請各位先進前輩們不吝嗇的指教,謝謝。