Navigating the reCAPTCHA Architecture

February 8, 2024


緣起

當有了可以填寫表單的網站後, 慢慢就會發現有很多的網路爬蟲會用程式自主地填表單塞廣告訊息, 或甚至嘗試攻擊,

為了避免相關資源的浪費, 常見的做法就是在送出資料到server的行為進行一個非機器人的驗證


本篇文章會簡要地說明google reCAPTCHA 的原理以及實際安裝


首先我們先來了解reCAPTCHA 的最終呈現


只有右下角顯示這個網頁有被reCAPTCHA保護, 連勾選我是機器人的這個check box 都不需要了!


我們來探討一下為什麼可以這樣做, 首先來看一下填完表單送出後會發生的事情, 如下步驟

1. end user透過從server取回的html填寫表單後送出

2. 預先埋設的google js會開始作用將使用者的一些關鍵事件蒐集加密post給google

    a.具體是什麼事件不太清楚, 要我猜是專門用來判斷是否為機器人的關鍵事件, 比如說滑鼠座標事件等等…

3. google 會回應一個權杖token給我們到私人的server做第二段驗證

4. 送出的表單資料會加上這個參數及token帶到後端

5. 後端要寫一隻API或是擴充既有的表單來接住這個token並且轉發給google進行驗證

    a. 注意, 這邊需要申請google API key才能正確呼叫

6. 取回google的評估結果, 可以由tokenProperties裡面的valid參數來確認是否驗證成功

7. 依據錯誤處理原則進行頁面的響應


基於步驟2的事件蒐集, google已經幫你打好分數判斷是不是機器人, 不需要另外要使用者輸入像是圖像辨識的內容來驗證了


實作前準備

1. 一個自有的網站, 當然是有先架好網站才有這個煩惱

2. 申請google cloud 的帳號並在google cloud console 側選單的憑證項目中產生一個有效的API key

3. 啟動一個recaptcha專案取得站台金鑰(site key) https://www.google.com/recaptcha/about/

    (每個月有一百萬次的評估, 對於個人網站基本上是免費的)



進入實作

在建置recaptcha專案的時候, 已經有一個逐步的教學, 教網站的開發者如何將recaptcha設置在自己的網站上,

我這邊再結構化一下相關的操作


1. 前端頁面js埋設, 不管走哪個方法, 都是要埋設專屬於這個網站的js讓google可以運作喔

<head>
  <script src="https://www.google.com/recaptcha/enterprise.js?render=YOUR_SITE_KEY"></script>
  <!-- Your code -->
</head>

2. 前端表單填完的事件綁定取權杖(token), 有兩種實作方法, 分別為

  a. html按鈕事件

<button class="g-recaptcha"
    data-sitekey="YOUR_SITE_KEY"
    data-callback='onSubmit'
    data-action='submit'>
  Submit
</button

<!-- Replace the variables below. -->
<script>
  function onSubmit(token) {
    document.getElementById("demo-form").submit();
  }
</script>

  b. 客製頁面事件綁定

grecaptcha.enterprise.ready(async () => {
    const token = await grecaptcha.enterprise.execute('YOUR_SITE_KEY', {action: 'LOGIN'});
});

3. 後端開發API 將權杖(token) , API key , site key , recaptcha project ID 組成的資訊post 給google 取回評估結果

  a. 不管是哪個語言, 接到前端拋出的token最終要透過RESTful API將資料以這樣的規格送給google

{
  "event": {
    "token": "{{token}}",
    "expectedAction": "YOUR_USER_ACTION",
    "siteKey": "YOUR_SITE_KEY"
  }
}

  b. URL規則如下

verifyUrl = "https://recaptchaenterprise.googleapis.com/v1/projects/" + projectId + "/assessments?key=" + apiKey;

4. 回應解析, 後端的資料解析則要著重於tokenProperties 這個物件裡面的valid 參數, 可以參考以下的sample

  {

"tokenProperties": {
    "valid": false,
    "invalidReason": "EXPIRED",
    "hostname": "",
    "androidPackageName": "",
    "iosBundleId": "",
    "action": "",
    "createTime": "2024-02-08T04:21:40.837Z"
  }

5. 當一切都串通之後就會從recaptcha後台看到網站已經受到保護, 這時就可以佈署囉