Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
在解決問題之道上不斷前行
Google reCAPTCHA 是一種常見的機器人驗證技術,用來區分人類使用者和自動化程式。現在主流有 v2 和 v3 兩種版本,是擁有免費額度的付費服務。
先前都只有透過打包好的 WordPress 外掛來實作,這次有機會在Nuxt3的前端專案中自己寫,就趁機記錄一下自己的理解與過程。
本次使用的是 reCAPTCHA v3 ,特點在於不用跟介面互動就能取得辨識結果,好處就是網站對使用者的驗證只會在背景處理,不影響使用體驗。
reCAPTCHA v3的技術原理大概可以這樣理解:
實作邏輯的話,其實就是跟 reCAPTCHA 服務取用資料這樣。
以下是我對 reCAPTCHA 溝通的理解:
首先註冊並申請 Google reCAPTCHA 服務。
網站前端載入 reCAPTCHA SDK,當使用者執行需驗證的操作時,呼叫grecaptcha.execute(), reCAPTCHA 服務會分析使用者行為後回傳 token。
前端將 reCAPTCHA token 連同表單數據或 API 請求一起發送給後端。
後端使用密鑰(secret key)向 Google reCAPTCHA API 發送驗證請求。
JSON 格式的回應包含:
success: 驗證是否成功(true/false)
score: 闕值,人類可能性分數(0.0-1.0)
action: 觸發驗證的行為名稱
challenge_ts: 時間戳記
hostname: 網站域名
我這次使用的 reCAPTCHA v3 會回傳 0.0 到 1.0 之間的分數,此分數表示使用者行為的「人類可能性」,管理者可自行決定接受的閾值(例如 0.5)高於閾值就允許後續操作,低於則可能需要額外驗證或拒絕請求。
我使用 vue-recaptcha-v3 ,自行建立 plugin 管理與啟動 reCAPTCHA,因為只有前端實作,所以很快就處理好了。
recaptcha.client.js
import { VueReCaptcha } from 'vue-recaptcha-v3'
export default defineNuxtPlugin(async (nuxtApp) => {
const config = useRuntimeConfig()
// 確保 siteKey 存在並輸出調試信息
console.log('Initializing reCAPTCHA with config:', {
siteKey: config.public.recaptchaSiteKey,
isDevelopment: process.env.NODE_ENV === 'development'
})
if (!config.public.recaptchaSiteKey) {
console.error('reCAPTCHA site key is missing')
return
}
try {
await nuxtApp.vueApp.use(VueReCaptcha, {
siteKey: config.public.recaptchaSiteKey,
loaderOptions: {
useRecaptchaNet: true, // 從 recaptcha.net 載入 script
autoHideBadge: false,// 隱藏標籤
explicitRenderParameters: {
badge: 'bottomright',
size: 'invisible'
}
}
})
// 驗證 reCAPTCHA 是否正確載入
const recaptcha = await window.grecaptcha
if (!recaptcha) {
throw new Error('reCAPTCHA not loaded properly')
}
console.log('reCAPTCHA plugin initialized successfully')
} catch (error) {
console.error('Failed to initialize reCAPTCHA:', error)
}
})
然後在 .env 和 nuxt.config 放好 API_KEY
例如在登入時就宣告上述的流程即可
import { useReCaptcha } from 'vue-recaptcha-v3'
const { executeRecaptcha, recaptchaLoaded } = useReCaptcha()
const handleLogin = async (e) => {
// 執行 reCAPTCHA 驗證
console.log('開始執行 reCAPTCHA 驗證')
const recaptchaToken = await executeRecaptcha('login')
console.log('recaptchaToken:', recaptchaToken)
// 發送登入請求
const response = await $fetch(`/api/login`, {
method: 'POST',
body: {
account: account.value,
password: password.value,
recaptchaToken: recaptchaToken
}
})
if (response) {
//後端回傳闕值做後續處理
}
}
後端就要另外寫一隻配合密鑰的請求去詢問結果。
成功載入的話,網站會出現 reCAPTCHA 的標籤,預設在右下方。