Les attaques par force brute pour deviner les mots de passe restent une menace réelle pour la sécurité des sites web. Ce tutoriel fournit un guide étape par étape pour sécuriser le formulaire de connexion du framework Yii2 en activant automatiquement la validation CAPTCHA après plusieurs tentatives de connexion échouées, renforçant ainsi la défense de votre application.
Pourquoi le CAPTCHA est-il Crucial pour la Connexion ?
Les attaques par force brute sont une méthode ancienne mais toujours efficace. Les attaquants utilisent des bots pour essayer automatiquement des milliers de combinaisons nom d’utilisateur/mot de passe. Un formulaire non protégé peut mener à la compromission de comptes administrateurs.
- Bloque les Bots : Le CAPTCHA (Test de Turing public complètement automatisé pour différencier les humains des ordinateurs) est conçu pour distinguer les humains des robots.
- Augmente la Difficulté : Déclencher un CAPTCHA après plusieurs échecs augmente considérablement l’effort requis par l’attaquant.
- Stratégie de Défense en Profondeur : Le CAPTCHA est une couche de sécurité supplémentaire vitale.
Implémenter le CAPTCHA de manière conditionnelle (seulement quand c’est nécessaire) maintient une bonne expérience utilisateur tout en créant une barrière pour les bots.
Étape 1 : Modifier le Modèle LoginForm.php
Ajoutez d’abord une propriété pour le CAPTCHA et sa logique de validation au modèle `LoginForm`. La clé est de rendre le CAPTCHA obligatoire uniquement après un certain nombre d’échecs.
<?php
namespace app\models;
use Yii;
use yii\base\Model;
class LoginForm extends Model
{
public $username;
public $password;
public $rememberMe = true;
public $verifyCode; // Nouvelle propriété pour le CAPTCHA
// ... autre code existant ...
public function rules()
{
return [
// Règles pour le nom d'utilisateur et le mot de passe
[['username', 'password'], 'required'],
['rememberMe', 'boolean'],
['password', 'validatePassword'],
// RÈGLES CAPTCHA : Obligatoire seulement si loginFailed est vrai
['verifyCode', 'required', 'when' => function($model) {
return $model->loginFailed;
}, 'message' => 'Le code CAPTCHA est requis après plusieurs échecs.'],
['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)) {
// LOGIQUE CLÉ : Incrémenter le compteur d'échecs
$attempts = Yii::$app->session->get('_loginAttempts', 0) + 1;
Yii::$app->session->set('_loginAttempts', $attempts);
$this->addError($attribute, 'Nom d\'utilisateur ou mot de passe incorrect.');
} else {
// Réinitialiser le compteur en cas de succès
Yii::$app->session->remove('_loginAttempts');
}
}
}
// Getter pour vérifier l'état d'échec
public function getLoginFailed()
{
// Le CAPTCHA se déclenche après 3 échecs ou plus
return Yii::$app->session->get('_loginAttempts', 0) >= 3;
}
// ... méthode getUser() et autres ...
}Explication du Code Clé :
- La propriété
$verifyCodecontient la saisie CAPTCHA de l’utilisateur. - La méthode
getLoginFailed()vérifie la variable de session_loginAttempts. Elle renvoietruesi les échecs ≥ 3. - Le paramètre
'when'assure que les règles pourverifyCodes’appliquent seulement siloginFailedesttrue.
Étape 2 : Afficher le CAPTCHA dans la Vue Login.php
Modifiez ensuite la vue de connexion pour afficher le widget CAPTCHA seulement lorsque la condition $model->loginFailed est remplie.
<?php
use yii\helpers\Html;
use yii\bootstrap5\ActiveForm; // ou yii\widgets\ActiveForm
/* @var $this yii\web\View */
/* @var $form yii\widgets\ActiveForm */
/* @var $model app\models\LoginForm */
$this->title = 'Connexion';
?>
<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() ?>
<!-- SECTION CONDITIONNELLE DU CAPTCHA -->
<?php if ($model->loginFailed): ?>
<div class="alert alert-warning">
Trop de tentatives de connexion échouées. Veuillez vérifier que vous êtes humain.
</div>
<?= $form->field($model, 'verifyCode')->widget(\yii\captcha\Captcha::className()) ?>
<?php endif; ?>
<div class="form-group">
<?= Html::submitButton('Se connecter', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>Étape 3 : Configurer l’Action CAPTCHA dans le Contrôleur
Le widget CAPTCHA nécessite une action dédiée dans le contrôleur. Assurez-vous que l’action ‘captcha’ est configurée dans `SiteController`.
<?php
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
// ... autres actions() ...
public function actions()
{
return [
'error' => ['class' => 'yii\web\ErrorAction'],
// L'ACTION CAPTCHA DOIT ÊTRE PRÉSENTE
'captcha' => [
'class' => 'yii\captcha\CaptchaAction',
'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
'minLength' => 4,
'maxLength' => 5,
'offset' => 2,
'testLimit' => 1,
],
// ... autres actions ...
];
}
// ... actionLogin() et autres méthodes ...
}Notes Importantes et Sécurité Supplémentaire
- Basé sur la Session : Cette implémentation repose sur les sessions PHP. Assurez-vous que leur configuration est sécurisée.
- Pas la Seule Solution : Le CAPTCHA doit être combiné à d’autres mesures :
- Limitation du Taux de Connexion : Utilisez des composants comme `yii\filters\RateLimiter` .
- Mots de Passe Forts : Imposez des mots de passe complexes.
- Journalisation : Enregistrez toutes les tentatives de connexion.
- Réinitialisation du Compteur : Le compteur se réinitialise après une connexion réussie. Une réinitialisation basée sur le temps est aussi possible.
En implémentant ce CAPTCHA conditionnel, vous ajoutez une couche de sécurité vitale qui perturbe intelligemment le flux automatisé des attaques par force brute, tout en conservant une bonne expérience utilisateur.


