Enjoy Your Coding

Google reCAPTCHA 我不是機器人

本篇文章將帶讀者簡單了解為何需要用Captcha(圖片驗證碼),並簡介Google reCAPTCHA這項第三方驗證服務,透過撰寫簡單範例程式來呈現。

首先,我們先來淺談一下「什麼是Captcha」「為何需要Captcha這項技術?」

什麼是Captcha (圖形驗證碼)

許多網頁表單最後,會有一張圖片及文字方塊,並說明您需要輸入與圖片相同的文字內容,通常以變形的文字圖案讓使用者辨識,無法用機器做辨識。

alt text

為何需要Captcha這項技術?

為了保護網站不被網頁機器人攻擊。網頁機器人的技術原理其實與瀏覽器一樣是基於HTTP的理論下時做出來的一個應用程式。撰寫人員可透過Wireshark、Fiddler或瀏覽器開發人員工具去研究一個網頁送出表單過程中,送了哪些資料,中間做了哪些事情、驗證等。

舉個例子,如果我們今天想寫一個可以自動去購票網站幫我們搶票的機器人,可透過開發人員工具去檢查從登入、Cookie的變化、網頁重新整理等待開放、購票、結帳過程中,經過了哪些步驟,又可以針對HTML或其他文件內容的變化來判斷是否開放訂票...等等步驟,並在撰寫網頁機器人的過程中,去模擬搶票的完整步驟,來達成自動化。

在過程中,伺服器端可判斷客戶端IP Address是否經常性的要求取得網頁資料(例如: 不停重新整理網頁),也可以透過Cookie來進行輔助等相關方式。

購票網站為了確保自身的網站不會網頁機器人輕易地攻擊及搶票,會加上由亂數產生的Captcha圖案在網頁表單的最後,僅讓使用者可以辨識出文字圖片的內容,網頁機器人無法辨識,因此無法作到自動化搶票,進行接下去的步驟。

人工智慧的普及

由於人工智慧的普及,搭配機器學習,若產生Captcha的演算法不夠複雜,變化度不夠高。網頁機器人可透過一定時間的學習,搭配程式的修正,慢慢學會辨識出網站Captcha的內容。在部分網站中,可能已造成威脅,若將演算法調整,又不能過於複雜,使用者可能無法辨識。

Google reCaptcha 的出現

第一代

reCAPTCHA一開始是由CMU (Carnegie Mellon University)於2009年,開發的系統,這個系統是透過從書本掃描的內容,無法使用OCR (Optical Character Recognition)技術去辨識文字的影像,作為網頁表單會出現的Captcha。2009年,Google收購了reCAPTCHA。

alt text

第二代

No CAPTCHA reCAPTCHA

alt text

在2013年,Google 開始研發新一套的reCAPTCHA,透過瀏覽器與使用者互動的分析,來預測這個使用者是否有可能為機器人。

驗證過程使用者只需點選上圖中的,I'm not a robot的核取方塊,如果使用者可能為機器人,將會透過填寫驗證碼或選取符合問題的圖片(如下圖)來辨別使用者是否為人類。該服務於2014年正式釋出。

alt text

第三代?

在撰寫這份文章的同時,搜尋Google reCAPTCHA後,居然發現到Google已經在做新的CAPTCHA技術,Invisible reCAPTCHA,這項技術的介紹,將在之後正式Release後,做相關介紹。

實作 - 用戶端 Client Side

接下來的內容將會透過撰寫簡單的程式來呈現Google reCAPTCHA的驗證方式。

1.申請 Google 帳號

請先註冊一個Google 帳號,以便後續啟用reCAPTCHA的服務

2.前往Google reCATPCHA 網站

alt text

進去後會跳出此畫面Invisible reCAPTCHA,不知道這次是不是不用點I am not a robot,但目前新版reCAPTCHA還在開發中,相關API(Application Programming Interface)可能還會有變更,所以各位麻煩先按CONTINUE跳過,本篇文章介紹第二代的reCAPTCHA實作應用。

進入畫面後請點選畫面右上角的Get reCAPTCHA,並登入Google Account alt text

alt text

登入成功後,若是第一次使用,會看到上圖畫面,麻煩您新增一個名稱+網域,本範例填寫的內容皆使用Localhost alt text

送出資料後,會顯示相關設定的資料及步驟,如下圖。 alt text

要載入reCAPTCHA的JS Library,並在要驗證的表單標籤裡面加上reCAPTCHA的設定。設定後的HTML如下:

<!DOCTYPE html>
<html lang="zh-tw">

<head>
    <meta charset="UTF-8">
    <title>Google reCAPTCHA Demo</title>
    <script src='https://www.google.com/recaptcha/api.js'></script>
</head>

<body>
    <form action="POST">
        <h3>登入</h3>
        帳號: <input type="text" name="username" />
        <br/> 
        密碼: <input type="password" name="password" />
        <div class="g-recaptcha" data-sitekey="6LdQahYUAAAAAJDSDhs-LcZeuGTSIoaSHwHnFSX1"></div>
        <button type="submit">送出</button>
    </form>
</body>

</html>

上面網頁透過瀏覽器開啟後,會出現以下畫面。

alt text

點選I'm not a robot後,即可完成驗證,驗證結果如下圖:

alt text

如果太久沒送出表單的話...會跑出expired,如下圖:

alt text

若是有其他額外的設定,例如: 主題、使用者驗證後回應、驗證碼過期回應之類,可參考下列連結reCAPTCHA文件:

https://developers.google.com/recaptcha/docs/display#render_param

接者,透過瀏覽器的開發人員工具我們可以發現我們的HTML有些內容上的變更(如下圖),原先的reCAPTCHA設定時貼上的HTML,裡面長出了一個iframe及textarea。在驗證成功後,看不見的textarea裡面會Google reCAPTCHA Service回傳的response value,送出表單時,會將此textarea的value一起送回給後端進行處理。

alt text

實作 - 伺服器端 Server Side

在伺服器端,使用任何語言皆可進行驗證,可透過Google Search下關鍵字:「程式語言名字 http post data」來尋找相關用法。

使用FORM POST的方式傳遞至https://www.google.com/recaptcha/api/siteverify

POST Body:

欄位名稱 說明
secret 請使用之前新增reCAPTCHA產生的secret
response Client端回傳的response
remoteip 非必填,若透過公司區網連到的網站,需特別注意此IP並非區網IP,是公司Client端對外IP

本篇以POSTMAN作為一個範例來呈現驗證的方式。

POST資料的設定如下圖:

alt text

成功的回傳範例如下:

{
  "success": true,
  "challenge_ts": "2017-02-21T05:51:43Z",
  "hostname": "localhost"
}

失敗的回傳範例如下:

{
  "success": false,
  "challenge_ts": "2017-02-21T05:40:02Z",
  "hostname": "localhost"
}

若success為true,代表驗證成功。

其他注意事項

  • Client端及Server端皆要是可連接Google的網站,若為公司內部不對外的網站,需特別注意Server端的防火牆設定,不適合完全封閉式的網站
  • Server端一定要驗證Client端的response是否為有效的,若不這麼做,網頁機器人一樣可自動搶票或購物等