[Codeingitor4] 使用recaptcha v3前後端認證

URL Link //n.sfs.tw/16062

2023-01-19 16:55:14 By 張○○

為了防止機器人說惡意攻擊,我們引入了 captcha,就是那個亂七八糟的字要人類去辨識內容的輸入框,但那種東西其實是廢物,因為目前的辨識軟體早就能輕鬆的破解內容了(請看結論)。

此外還會造成使用者的厭煩,在資安上大概只是為了心裡上的安慰而已,安慰資料檢查業務的人,沒有實際的意義。

anyway,我們引入google 的recaptcha來解決這個問題,recaptcha有v2和v3兩個版本,v3的話不必按那個我是人類的核取框,也不必點擊那些看不懂的圖片(例如問你那些圖片有單車)。

所以我採用v3的版本。

 

使用 recaptcha v3

申請和設定

進到 google rechptcha的頁面

https://www.google.com/recaptcha/about/

進到console admin中新增一個服務

https://www.google.com/recaptcha/admin/

相關設定可以參考[2]的說明文件,這裡略。

申請完畢會拿到一個sitekey和secret,sitekey是前端用的,secret是後端用的。

一次可以同時設定多個網域。

放到網頁上

官網[3]的說明這部分很簡單,原理是在送出submit之後,先進行recaptcha的驗證,通過再把表單送到後端,只要三步驟就完成。

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

1. 加入js

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

2. 寫入一個函數,替你的 form 作送出的動作,記得替你的form加上id

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

3. 把你的 submit 按鈕改成

<button class="g-recaptcha"
        data-sitekey="<<改成你的reCAPTCHA_site_key>>"
        data-callback='onSubmit'
        data-action='submit'>Submit
</button>

這樣你的按鈕右下就會出現recaptcha的符號,大功告成!

咦?!這樣就好了?

其實我在這地方想了很久,第2個步驟並沒有任何的防止動作啊?

 

伺服器端檢查

後來參考[2]的說明給了靈感自己完成伺服端的驗證。

伺服器取得由前端送來的tocken,進行檢查。

我的作法是透過 ajax的方式送到後端檢查,取得recaptcha的分數。

他的分數是 0~1。0是機器人,1是人類。

以下程式取得此分數

PHP 範例

  public function getReCaptcha($token=""){
     if(!$token)return 0;
     $client = \Config\Services::curlrequest(); //引用curl函數
     $uri = 'https://www.google.com/recaptcha/api/siteverify';
     $response = $client->request('POST', $uri, [
          'form_params' => [
            "secret"=> <recaptchaSecret 放這>,
            "response" => $token,
            "remoteip" => $_SERVER["REMOTE_ADDR"]
          ],
     ]);
     $body = $response->getBody();
     if($body){
         $para = json_decode($body,true);
         return $para['score'];
     }
     // 預設給分=0.5通過,問不到的情況
     return 0.5;
 }

第3行 引用curl的函數,因為我是用ci4,所以可以直接這樣引用。

第12行 取得的$body物件,內容欄位大概如下:

        { "success": true, "challenge_ts": "2023-01-19T06:01:12Z", "hostname": "n.sfs.tw", "score": 0.9, "action": "submit" }

後端程式由取回的分數判斷是否要回應正確的資料。這部分就請自行依需要設計。

 

結論

使用 recaptcha v3是明智的選擇,不必有繁瑣或多餘的操作。

記得有看過一個影片,验证码大战AI:神仙打架,我们遭殃,验证码还能变简单吗? Verification code vs. AI: Can verification code become simpler?指出(3:56秒處),

像下圖的驗證碼,ai的辨識度達到99.8%的準確率,而人類只有33.3%。換句話說,答錯的才是人類。

也許有人說你可以改驗證方式,但最後還是會輸給ai,所以最後驗證碼是要阻止人類使用服務。

總之結合recaptcha v3前後端驗證,可以防止機器人的攻擊。

 

參考資料

[1] https://www.google.com/recaptcha/about/

[2] https://www.letswrite.tw/recaptcha-v3/

[3] https://developers.google.com/recaptcha/docs/v3