Lewati ke konten

Laravel Shieldv1.2.x

Challenge

Challenge adalah jaring pengaman kedua. Kalau Shield menduga sesuatu mencurigakan tetapi belum cukup yakin untuk memblokir, ia mengarahkan pengunjung ke halaman pembuktian. Kalau berhasil, pengunjung dibolehkan melanjutkan dan ditandai sebagai orang yang sudah terbukti.

Challenge muncul ketika skor request berada di antara thresholds.challenge dan thresholds.ban:

$thresholds = [
'challenge' => 10, // mulai muncul challenge
'ban' => 20, // mulai kena ban
'strong_ban' => 30, // ban lebih lama
];

Jadi request dengan skor 14 mendapat challenge, bukan ban. Ini yang membuat mode: challenge jauh lebih aman daripada mode: enforce untuk situs yang masih mendapat traffic tinggi.

SHIELD_CHALLENGE=turnstile
Nilai Driver Kapan dipakai
turnstile Cloudflare Turnstile Pilihan kami. Bagus, cepat, dan punya kuota gratis.
recaptcha Google reCAPTCHA v3 Kalau Anda sudah memakai reCAPTCHA di situs.
google_recaptcha Sama dengan recaptcha Alias, untuk memudahkan.
null Tanpa pihak ketiga Development dan pengujian otomatis.

null membuat verifikasi selalu gagal kecuali token-nya persis test-token. Gunanya untuk development, bukan untuk produksi.

Di dashboard Cloudflare, bagian Turnstile, buat widget dengan tipe Managed. Cloudflare memberi Anda satu site key dan satu secret key.

SHIELD_CHALLENGE=turnstile
SHIELD_TURNSTILE_SITE_KEY=0x4AAAAAAA...
SHIELD_TURNSTILE_SECRET_KEY=0x4AAAAAAA...

site key aman untuk ditaruh di HTML — memang itu gunanya. secret key tidak boleh pernah masuk ke repository.

Cloudflare hanya mengirim challenge ke domain yang Anda daftarkan saat membuat widget. Kalau Anda lupa mendaftarkan localhost atau domain staging, widget tidak akan tampil saat development.

Saat Pengunjung mengirim token, server Anda meneruskannya ke Cloudflare:

POST https://challenges.cloudflare.com/turnstile/v0/siteverify

Isinya: secret, response (token dari widget), dan remoteip (IP pengunjung, opsional tapi membantu Cloudflare menilai).

Kalau Anda memakai proxy di depan Cloudflare, remoteip yang terkirim adalah IP proxy — bukan IP asli pengunjung. Cloudflare akan tetap memverifikasi, tapi penilaiannya sedikit kurang optimal. Isi bots.verification.ip_ranges dan konfigurasi proxy untuk mengatasi ini.

Alamat di atas bisa diganti lewat challenge.turnstile.verify_url kalau Anda mengarahkannya ke server verifikasi sendiri.

Shield membuat dua route untuk mekanisme ini:

Method Route Nama route Keterangan
GET /shield/challenge shield.challenge Menampilkan widget.
POST /shield/challenge/verify shield.challenge.verify Memverifikasi token. Dibatasi 10 permintaan per menit.
  1. Request mencurigakan → Shield membalas 401 dengan header X-Shield-Challenge: 1 dan body JSON yang memuat challenge_url.
  2. Klien membuka challenge_url. Halaman dirender dengan Cache-Control: no-store supaya tidak pernah tersimpan cache.
  3. Pengunjung menyelesaikan widget, lalu form mengirim token ke /shield/challenge/verify.
  4. Server memverifikasi token ke Cloudflare.
  5. Kalau gagal, pengunjung dikembalikan ke halaman challenge dengan ?error=1.
  6. Kalau berhasil, Shield menandai IP sebagai “sudah lolos”, memasang trusted cookie, lalu mengarahkan balik ke halaman tujuan.

Setelah lolos, Shield memasang cookie bernama shield_trusted. Atributnya:

Atribut Nilai Untuk apa
HttpOnly aktif JavaScript tidak bisa membacanya.
Secure aktif Hanya dikirim lewat HTTPS.
SameSite Lax Dikirim untuk navigasi tingkat atas saja.

Cookie ini yang membuat pengunjung tidak di-challenge berulang kali selama mengjelajah. Masa berlakunya diatur oleh:

SHIELD_TRUSTED_TTL_MINUTES=60

Setel trusted.enabled ke false kalau Anda ingin setiap request yang mencurigakan selalu di-challenge ulang.

Halaman challenge menerima parameter redirect untuk menentukan tujuan setelah berhasil. Nilainya divalidasi ketat sebelum dipakai:

Masukan Hasil
/produk/123 Dipakai.
https://jahat.example Dibuang, dan pengunjung diarahkan ke /.
//jahat.example Dibuang, karena berarti URL protocol-relative.
/x:y Dibuang, karena terbaca seperti scheme.
\ atau %5c Dinormalkan menjadi /, lalu diperiksa ulang.

Kalau nilai parameter tidak aman, pengunjung diarahkan ke beranda. Ini mencegah attacker memakai challenge sebagai pembuka open redirect.

SHIELD_BRANDING_TITLE=Toko Online Aman
SHIELD_BRANDING_ACCENT=#22d3ee
SHIELD_BRANDING_BG=#0b1220

Kalau Anda ingin kendali penuh atas HTML, publish view bawaan lalu ubah:

Terminal window
php artisan vendor:publish --provider="Ganadev\Shield\Laravel\ShieldServiceProvider" --tag=shield-views

Lalu arahkan views.challenge ke view Anda sendiri:

SHIELD_VIEW_CHALLENGE=my-challenge

Variabel yang tersedia di view: siteKey, testToken, csrfToken, redirect, error, dan branding.

Dengan SHIELD_CHALLENGE=null, Anda bisa menguji alur challenge secara deterministik:

Terminal window
curl -i "http://localhost:8000/shield/challenge"

Verifikasi manual dengan token yang benar:

Terminal window
curl -i -X POST http://localhost:8000/shield/challenge/verify \
-d "shield_challenge_token=test-token" \
-d "redirect=/"

Token yang salah akan mengembalikan redirect ke ?error=1.

Periksa satu per satu:

Gejala Penyebab yang paling mungkin
Widget tidak tampil sama sekali site_key kosong, atau domain Anda belum didaftarkan di Cloudflare.
Selalu gagal verifikasi secret_key salah, atau token kedaluwarsa.
Mengalihkan ke ?error=1 terus-menerus remoteip tidak dipercaya, atau cookie di-domain lain.
Pengunjung kena challenge berulang Trusted cookie tidak tersimpan — periksa HTTPS dan SameSite.
Semua orang kena challenge Skor behavior terlalu rendah, atau thresholds.challenge terlalu kecil.

Untuk melihat komponen yang berjalan, gunakan php artisan shield:health.

Powered by PT Ganadev Multi Solusi