อยากทำให้ Supabase เข้าใจว่า ต้องใช้ Captcha Turnstile ของ Cloudflare ด้วย
เพิ่มเว็บเราเข้า Cloudflare Turnstile ก่อน
เข้าสู่ระบบของ Cloudflare แล้วไปที่เมน Turnstile หากมีเว็บของเราเพิ่มอยู่แล้วจะมีรายการแสดงขึ้นมา
หากไม่มีก็ไปกดเพิ่มก่อน โดยใส่ชื่อเว็บที่ต้องการ และ โดเมนที่เราเพิ่มไว้ใน Cloudflare
เมื่อเพิ่มเรียบร้อยเราจะได้
- Site Key: 0x4AAAAAAAKNlgbD8W2wht3r
- Secret Key: 0x4AAAAAAAKnlgMqynfdAe1heBR6oM_dJvg
เราจะเอา 2 อันนี้ไปใช้
ไปตั้งค่าที่ Supabase
เข้าสู่ระบบ Supabase ให้เรียบร้อย เข้าไปที่โครงการที่ต้องการ จากนั้นไปที่ Settings -> Auth
- ในหัวข้อ Security and Protection ให้ Enable Captcha Protection
- แล้วเลือก Captcha Providers เป็น Turnstile (Cloudflare)
- จากนั้นเอา Secret Key ที่ได้จาก Cloudflare => 0x4AAAAAAAKnlgMqynfdAe1heBR6oM_dJvg ไปใส่ในช่อง Captcha secret
ติดตั้ง Package @nuxtjs/turnstile
@nuxtjs/turnstile ด้วยคำสั่ง
npm install -D @nuxtjs/turnstile
แก้ไขไฟล์ nuxt.config.ts
- เพิ่มชื่อ @nuxtjs/turnsile เข้าไปที่ modules
- เพิ่มค่า turnstile -> siteKey ด้วย Site Key ที่เราได้มา คือ 0x4AAAAAAAKNlgbD8W2wht3r
- เพิ่มค่า runtimeConfig -> turnstile -> secretKey ด้วย Secret Key ที่เราได้มา คือ 0x4AAAAAAAKnlgMqynfdAe1heBR6oM_dJvg
/** file: nuxt.config.ts **/ export default defineNuxtConfig({ modules: ['@nuxtjs/turnstile'], turnstile: { siteKey: '0x4AAAAAAAKNlgbD8W2wht3r', }, runtimeConfig: { turnstile: { secretKey: '0x4AAAAAAAKnlgMqynfdAe1heBR6oM_dJvg', }, }, })
หน้าเข้าสู่ระบบ
มีการเพิ่ม <NuxtTurnstile v-model=”turnstileToken” ref=”turnstile”> เข้าไปใน form
ดูดีๆ ชื่อตัวแปรจะคล้าย ๆ กัน คือ turnstile, turnstileToken เนื่องจากหากไม่แยกมันสั่ง reset() ไม่ได้ เลยต้องทำการแยกให้ turnstile เป็น ref และ turnstileToken เป็น v-model
/** file: pages/login.vue **/ <script setup> const supabase = await useSupabaseClient(); const user = await useSupabaseUser(); if (user.value) { await navigateTo("/admin/dashboard", { replace: true }); } const loading = ref(false); const email = ref(""); const password = ref(""); const turnstile = ref(); const turnstileToken = ref(); const handleLogin = async () => { try { loading.value = true; const { error } = await supabase.auth.signInWithPassword({ email: email.value, password: password.value, options: { captchaToken: turnstileToken.value }, }); if (error) { return false; } await navigateTo("/admin/dashboard", { replace: true }); } catch (error) { console.log(error.error_description || error.message); } finally { turnstile.value?.reset(); loading.value = false; } }; </script> <template> <div class="flex justify-center items-center"> <form class="bg-yellow-500 flex flex-col gap-5 px-20 pb-20 pt-10" @submit.prevent="handleLogin" > <img src="/images/logo.png" alt="KanexKane" class="w-32 mx-auto" /> <div class="join"> <Icon name="material-symbols:person-4" size="2em" class="absolute ml-2 mt-2 text-base-300" /> <input type="text" placeholder="E-mail" class="input w-full max-w-xs pl-14" v-model="email" autocomplete="email" /> </div> <div class="join"> <Icon name="carbon:password" size="2em" class="absolute ml-2 mt-2 text-base-300" /> <input type="password" placeholder="Password" class="input w-full max-w-xs pl-14" v-model="password" autocomplete="current-password" /> </div> <NuxtTurnstile v-model="turnstileToken" ref="turnstile" /> <button class="btn btn-primary rounded-full px-14" :disabled="loading"> {{ loading ? "Please wait..." : "Login" }} </button> </form> </div> </template>
ทำไมต้องมีการทำ turnstile.value.reset()
เพราะหากมีการเข้าสู่ระบบผิดพลาด การกดซ้ำอีกครั้งโดยไม่ทำการ reset ก่อน จะทำให้เกิดการ Error ทางฝั่ง Supabase บอกว่ามัน Duplicate ก็เลยต้องทำการ reset ทุกครั้งที่จะทำการคลิกปุ่ม Login