# Vue 實作 Google reCAPTCHA / Google 非機器人驗證 ## 前言 因為工作上的需要,所以要來研究Google reCAPTCHA,公司是用Vue,所以會來用Vue來實做看看,後續看看能不能整合進去公司的Nuxt3的前台~最下面有本次實作的範例檔案,有需要可以直接取XD~ ## Google reCAPTCHA 因為網站安全性問題,或是要防止機器人來到你的網站,佔用你的伺服器空間,所以很多網站都會連接Google reCAPTCHA,來讓Google幫你檢驗,當前使用者是不是機器人~ 這功能應該很常見,想必大家一定有看過一個勾勾旁邊是我不是機器人,或是一個九宮格請你選取題目指示的圖片,這些都是Google reCAPTCHA的實作。 Google reCAPTCHA主要有以下幾種: 1. google reCAPTCHA v2 * ![](https://i.imgur.com/JUL9v3K.png) * 會有一個核取框,問你是不是機器人,在google的檢查機制下如果覺得你是機器人,就會出現九宮格選取框,再來依照題目的要求選取即可。 2. google reCAPTCHA v3 * 全在背景執行,google會給當前使用者進行評分,從0.0~1.0,開發者可以自行決定,多少分以下視為機器人! 3. google reCAPTCHA 企業版 * 目前據了解,會有更多管理上的功能,且也不會有驗證次數上的限制,因為**reCAPTCHA v2 v3有每個月一百萬次**的上限! ## 註冊Google reCAPTCHA 先到[Google reCAPTCHA](https://www.google.com/recaptcha/about/),選取紅色框框的`v3 Admin Console`。 ![](https://i.imgur.com/nGcTXsE.png) 接下來填入一些基本的資料進行註冊吧!有幾點可以注意: * reCAPTCHA v2 v3依自己的需求使用,如果都需要則要分為兩個進行創立 * 網站可以填入127.0.0.1和localhost,如有需要可以填自己區網的ip ![](https://i.imgur.com/fwOpYh4.png) 提交後,就可以看到金鑰了,可以不用複製,後續進到Google reCAPTCHA的站台還是可以看到~在前端(Vue)會使用到的都只會是`網站金鑰`! ![](https://i.imgur.com/S7knwuE.png) 那Google reCAPTCHA的註冊前置的部分就到這邊,可以去準備Vue的環境了,這邊reCAPTCHA v2 v3都會實作,所以要去註冊兩個~~~ ![](https://i.imgur.com/0Wg6TSY.png) ## 建立Vue專案 那現在就先簡單的建立Vue3 Template: * 使用Vue3 * Vite * Typescript 可以使用你喜歡的套件管理器,以下範例皆使用pnpm。 ``` bash pnpm create vite@latest [vue3-recaptcha-example] -- --template vue-ts cd vue3-recaptcha-example pnpm install pnpm run dev ``` 先檢測看看是否能正常啟動~ ## 實作reCAPTCHA v2 可以正常啟動後,先下載套件[vue3-recaptcha2](https://www.npmjs.com/package/vue3-recaptcha2): ``` bash pnpm install vue3-recaptcha2 ``` 然後建立GoogleReCaptchaV2.vue進行import,這邊簡單的建立,可以依需求import在各個地方! ![](https://i.imgur.com/5L0dBnV.png) 接下來來實作GoogleReCaptchaV2.vue: 我習慣將相關的方法用類似物件的方式封裝關聯起來: ``` Typescript <script setup lang="ts"> import { reactive } from 'vue'; import vueRecaptcha from 'vue3-recaptcha2'; const instance_vueRecaptchaV2 = reactive({ // 請換成你註冊的 SiteKey // Please change to your SiteKey. data_v2SiteKey: '*****************************', recaptchaVerified: (response_token: string) => { console.log(response_token); // 連接後端API,給後端進行認證 // Connect to your Backend service. }, recaptchaExpired: () => { // 驗證過期後進行的動作 // After recaptcha is expired, the action you can do. console.log('驗證過期啦QAQ'); }, recaptchaFailed: () => { // 驗證失敗進行的動作 // After recaptcha is failed, the action you can do. }, }); </script> ``` ``` HTML <template> <vue-recaptcha :sitekey="instance_vueRecaptchaV2.data_v2SiteKey" size="normal" theme="light" hl="zh-TW" @verify="instance_vueRecaptchaV2.recaptchaVerified" @expire="instance_vueRecaptchaV2.recaptchaExpired" @fail="instance_vueRecaptchaV2.recaptchaFailed" /> </template> ``` 接下來在頁面上就可以看到,目前沒有調整樣式,可以依照需求去調整~ 可以在Component階段用一個div包著,import後進行排版! ![](https://i.imgur.com/XNyzTo4.png) 可以簡單測試看看,點擊我不是機器人後,核取框會打勾,且在開發人員的Console也有印出這次reCAPTCHA的Token,再去連接後端進行認證即可~ ![](https://i.imgur.com/2DUWmDZ.png) 當驗證過期時,功能也都正常,就可以依照需求進行操作啦! ![](https://i.imgur.com/2FI9Z51.png) 那到這邊,就已經完成了Google reCAPTCHA v2的Vue實作了! ## 實作reCAPTCHA v3 接下來要實作reCAPTCHA v3,先下載套件[vue-recaptcha-v3](https://www.npmjs.com/package/vue-recaptcha-v3): ``` bash pnpm install vue-recaptcha-v3 ``` 再來到`main.ts`對vue-recaptcha-v3進行註冊,其中[loaderOptions](https://github.com/AurityLab/recaptcha-v3/#load-options-usage)可以在vue-recaptcha-v3套件說明這邊依照自己的需求選取。 ``` Typescript main.ts import { createApp } from 'vue'; import './style.css'; import App from './App.vue'; import { VueReCaptcha } from 'vue-recaptcha-v3'; const app = createApp(App); app.use(VueReCaptcha, { // 請換成你註冊的 SiteKey // Please change to your SiteKey. siteKey: '*****************************', loaderOptions: { useRecaptchaNet: true, }, }); app.mount('#app'); ``` 進行註冊完後,你就可以發現在畫面右下角有Google reCAPTCHA v3的圖標,這個圖標也可以用Css style強制隱藏。 ![](https://i.imgur.com/HhCcjB4.png) 但如果你是**使用TypeScript+Vue3的Option Api**,就需要在src檔案目錄下新增`shims-vue-recaptcha-v3.d.ts`,才可以正常使用,如果是**Composition Api則可以跳過**! ``` Typescript shims-vue-recaptcha-v3.d.ts import { ReCaptchaInstance } from 'recaptcha-v3' declare module '@vue/runtime-core' { interface ComponentCustomProperties { $recaptcha: (action: string) => Promise<string> $recaptchaLoaded: () => Promise<boolean> $recaptchaInstance: ReCaptchaInstance } } ``` 接著建立GoogleReCaptchaV3.vue進行import,可以依需求import在各個地方!但這邊比較要注意的是reCAPTCHA v3主要是使用者在進行某一個事件時觸發,像是登入或是註冊發送表單的時候進行,這邊先以點擊Button當作觸發條件! ``` Typescript <script setup lang="ts"> import { reactive } from 'vue'; import { useReCaptcha } from 'vue-recaptcha-v3'; const { executeRecaptcha, recaptchaLoaded } = useReCaptcha()!; const instance_vueRecaptchaV3 = reactive({ executeRecaptcha: async () => { // (可選) 等待直到 recaptcha 載入完成 await recaptchaLoaded(); // 執行 "login" 狀態的 reCAPTCHA const token = await executeRecaptcha('login'); // 後續傳給後端進行認證 console.log(token); }, }); </script> ``` ``` HTML <template> <div class="v3-margin"> <button type="button" @click="instance_vueRecaptchaV3.executeRecaptcha" > Submit to active reCAPTCHA </button> </div> </template> <style scoped lang="css"> .v3-margin { margin-top: 20px; } </style> ``` 並在需要的地方進行import: ![](https://i.imgur.com/9S29UrU.png) 在畫面上就可以看到觸發reCAPTCHA的Button,按下去也可以觸發功能: ![](https://i.imgur.com/tXZsdAG.png) 那由於[vue-recaptcha-v3](https://www.npmjs.com/package/vue-recaptcha-v3),提供的方式是使用**provide/inject**的方式進行註冊,所以所有**有關套件的操作都要在vue的setup狀態**進行。 但依照上面的範例,所有狀態觸發都綁定在Button上面觸發,相對不彈性,所以將它額外移出去,到新建立的Composable去實作。我這邊想到的方法是建立Composable:useReCaptchaV3.ts,提供一個方法,當要使用發法的時候,傳vue-recaptcha-v3的實例(Instance)進去即可,相關實作如下: 建立`useReCaptchaV3.ts`,並實作: ``` Typescript import { IReCaptchaComposition } from 'vue-recaptcha-v3'; export async function useReCaptchaV3(useReCaptcha: IReCaptchaComposition) { const { executeRecaptcha, recaptchaLoaded } = useReCaptcha; // (可選) 等待直到 recaptcha 載入完成 // (optional) Wait until recaptcha has been loaded. await recaptchaLoaded(); // 執行 "login" 狀態的 reCAPTCHA // Execute reCAPTCHA with action "login". const token = await executeRecaptcha('login'); // 後續傳給後端進行認證 // Do stuff with the received token. console.log(token); } ``` 在需要用到reCAPTCHA v3的地方進行引入: ``` Typescript <script setup lang="ts"> import { useReCaptcha } from 'vue-recaptcha-v3'; import { useReCaptchaV3 } from '../composables/useReCaptchaV3'; const useReCaptchaInstance = useReCaptcha()!; </script> ``` ``` HTML <template> <div class="v3-margin"> <button type="button" @click="useReCaptchaV3(useReCaptchaInstance)"> Submit to active reCAPTCHA </button> </div> </template> <style scoped lang="css"> .v3-margin { margin-top: 20px; } </style> ``` 這樣一樣可以完成觸發,且更彈性、靈活,可以在各處依照需求引入! ![](https://i.imgur.com/yoq8cFk.png) ## 結論 那到目前為止,就完成了Google reCAPTCHA v2 v3的實作了,在依照跟後端的溝通進行驗證即可~沒有遇到什麼困難,算是很好接的Google Api了XD 那這邊附上實作的範例檔案:[vue3-recaptcha-example](https://github.com/ben890524/vue3-recaptcha-example)。 ###### tags: `Vue3` `Google reCAPTCHA`