Serangan brute force untuk menebak password masih menjadi ancaman nyata bagi keamanan website. Tutorial ini memberikan panduan langkah demi langkah untuk mengamankan form login pada framework Yii2 dengan mengaktifkan validasi CAPTCHA secara otomatis setelah beberapa kali percobaan login gagal, sehingga meningkatkan pertahanan layer aplikasi Anda.
Mengapa CAPTCHA Penting untuk Form Login?
Serangan brute force adalah metode lama yang tetap efektif dan sering digunakan peretas. Mereka menggunakan bot untuk mencoba ribuan kombinasi username dan password secara otomatis. Jika form login Anda tidak dilindungi, akun administrator dan data sensitif bisa direbut.
- Memblokir Bot: CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) dirancang khusus untuk membedakan manusia dan robot.
- Meningkatkan Kesulitan Serangan: Dengan menambahkan CAPTCHA setelah beberapa kegagalan login, Anda secara signifikan meningkatkan upaya yang dibutuhkan penyerang.
- Strategi Defense-in-Depth: CAPTCHA adalah salah satu lapisan keamanan tambahan yang wajib dipertimbangkan, selain juga menggunakan password yang kuat dan membatasi attempt login.
Mengimplementasikan CAPTCHA secara kondisional (hanya muncul saat diperlukan) menjaga user experience tetap baik bagi pengguna sah, sekaligus menjadi tembok bagi bot dan penyerang.
Langkah 1: Modifikasi Model LoginForm.php
Pertama, kita tambahkan properti untuk CAPTCHA dan logika validasinya di model `LoginForm`. Kuncinya adalah membuat CAPTCHA hanya wajib diisi setelah sejumlah percobaan login gagal.
<?php
namespace app\models;
use Yii;
use yii\base\Model;
class LoginForm extends Model
{
public $username;
public $password;
public $rememberMe = true;
public $verifyCode; // Properti baru untuk CAPTCHA
// ... kode lainnya ...
public function rules()
{
return [
// Aturan untuk username dan password
[['username', 'password'], 'required'],
['rememberMe', 'boolean'],
['password', 'validatePassword'],
// ATURAN CAPTCHA: Hanya diperlukan jika loginFailed true
['verifyCode', 'required', 'when' => function($model) {
return $model->loginFailed;
}, 'message' => 'Kode CAPTCHA wajib diisi setelah beberapa percobaan gagal.'],
['verifyCode', 'captcha', 'when' => function($model) {
return $model->loginFailed;
}],
];
}
public function validatePassword($attribute, $params)
{
if (!$this->hasErrors()) {
$user = $this->getUser();
if (!$user || !$user->validatePassword($this->password)) {
// INI INTINYA: Hitung jumlah percobaan gagal
$attempts = Yii::$app->session->get('_loginAttempts', 0) + 1;
Yii::$app->session->set('_loginAttempts', $attempts);
$this->addError($attribute, 'Username atau password salah.');
} else {
// Reset counter jika login sukses
Yii::$app->session->remove('_loginAttempts');
}
}
}
// Getter untuk mengecek status kegagalan
public function getLoginFailed()
{
// CAPTCHA muncul setelah 3 kali gagal
return Yii::$app->session->get('_loginAttempts', 0) >= 3;
}
// ... method getUser() dan lainnya ...
}Penjelasan Kunci:
- Properti
$verifyCodemenampung input CAPTCHA dari user. - Fungsi
getLoginFailed()memeriksa session_loginAttempts. Jika percobaan gagal ≥ 3, ia mengembalikantrue. - Parameter
'when'pada aturan validasi membuat aturan untukverifyCodehanya berlaku jikaloginFailedbernilaitrue. - Setiap kali validasi password gagal, counter di session bertambah. Login sukses akan mereset counter.
Langkah 2: Tampilkan CAPTCHA di View Login.php
Selanjutnya, kita modifikasi file view login agar menampilkan widget CAPTCHA hanya ketika kondisi $model->loginFailed terpenuhi.
<?php
use yii\helpers\Html;
use yii\bootstrap5\ActiveForm; // atau yii\widgets\ActiveForm
/* @var $this yii\web\View */
/* @var $form yii\widgets\ActiveForm */
/* @var $model app\models\LoginForm */
$this->title = 'Login';
?>
<div class="site-login">
<h1><?= Html::encode($this->title) ?></h1>
<div class="row">
<div class="col-lg-5">
<?php $form = ActiveForm::begin(['id' => 'login-form']); ?>
<?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'password')->passwordInput() ?>
<?= $form->field($model, 'rememberMe')->checkbox() ?>
<!-- BAGIAN CAPTCHA YANG KONDISIONAL -->
<?php if ($model->loginFailed): ?>
<div class="alert alert-warning">
Terlalu banyak percobaan login gagal. Harap verifikasi bahwa Anda adalah manusia.
</div>
<?= $form->field($model, 'verifyCode')->widget(\yii\captcha\Captcha::className()) ?>
<?php endif; ?>
<div class="form-group">
<?= Html::submitButton('Login', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>Langkah 3: Konfigurasi Action CAPTCHA di Controller
Widget CAPTCHA memerlukan sebuah action di controller untuk menghasilkan gambar dan memvalidasi kode. Pastikan action ‘captcha’ telah dikonfigurasi di `SiteController`.
<?php
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
// ... actions() lainnya ...
public function actions()
{
return [
'error' => ['class' => 'yii\web\ErrorAction'],
// ACTION CAPTCHA WAJIB ADA
'captcha' => [
'class' => 'yii\captcha\CaptchaAction',
'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null, // Penting untuk environment testing
'minLength' => 4, // Panjang minimal kode
'maxLength' => 5, // Panjang maksimal kode
'offset' => 2, // Tingkat kesulitan visual
'testLimit' => 1, // Berapa kali kode bisa digunakan (1 = sekali pakai)
],
// ... action lain ...
];
}
// ... actionLogin() dan method lainnya ...
}Konfigurasi seperti minLength, maxLength, dan testLimit membantu menyesuaikan tingkat keamanan dan kegunaan CAPTCHA sesuai kebutuhan aplikasi Anda .
Catatan Penting & Keamanan Tambahan
- Session-Based: Implementasi ini bergantung pada session PHP. Pastikan konfigurasi session server Anda aman.
- Bukan Satu-satunya Solusi: CAPTCHA adalah lapisan pertahanan yang baik, namun Anda harus mengombinasikannya dengan cara lain seperti:
- Membatasi Rate Login: Gunakan komponen seperti `yiifiltersRateLimiter` untuk membatasi jumlah request ke action login per IP dalam waktu tertentu .
- Password yang Kuat: Wajibkan penggunaan password kompleks untuk semua user, terutama admin.
- Log dan Monitoring: Catat semua percobaan login, baik yang berhasil maupun gagal, untuk analisis lebih lanjut.
- Reset Counter: Pada kode di atas, counter di-reset saat login sukses. Anda juga bisa menambahkan fitur reset setelah jangka waktu tertentu (misal, 30 menit) untuk user experience yang lebih baik.
Dengan menerapkan CAPTCHA kondisional ini, Anda telah menambahkan lapisan keamanan penting yang secara cerdas mengganggu alur otomatis serangan brute force, sambil tetap menjaga kemudahan bagi pengguna sah yang hanya sekali salah mengetik password.


