StartPHP-FrameworkYii2 Login mit CAPTCHA gegen Brute-Force sichern

Yii2 Login mit CAPTCHA gegen Brute-Force sichern

Advertisement

Brute-Force-Angriffe zum Erraten von Passwörtern sind eine reale Bedrohung für die Websicherheit. Diese Anleitung zeigt Schritt für Schritt, wie Sie das Login-Formular im Yii2-Framework schützen, indem nach mehreren fehlgeschlagenen Anmeldeversuchen automatisch eine CAPTCHA-Validierung aktiviert wird.

Advertisement

Warum CAPTCHA für das Login entscheidend ist

Brute-Force-Angriffe sind eine alte, aber effektive Methode. Angreifer nutzen Bots, um automatisch tausende Kombinationen aus Benutzername und Passwort zu testen. Ein ungeschütztes Formular kann zu kompromittierten Admin-Konten führen.

  • Blockiert Bots: CAPTCHA („Completely Automated Public Turing test to tell Computers and Humans Apart“) unterscheidet Menschen von Robotern.
  • Erhöht den Aufwand: Ein ausgelöstes CAPTCHA nach mehreren Fehlversuchen erhöht den Aufwand für Angreifer erheblich.
  • Verteidigungsstrategie: CAPTCHA ist eine wichtige zusätzliche Sicherheitsebene.

Die bedingte Implementierung von CAPTCHA (nur bei Bedarf) erhält die Benutzerfreundlichkeit und stellt gleichzeitig eine Barriere für Bots dar.

Schritt 1: Das LoginForm-Modell anpassen

Fügen Sie zunächst eine Eigenschaft für das CAPTCHA und seine Validierungslogik zum `LoginForm`-Modell hinzu. Der Schlüssel ist, das CAPTCHA erst nach einer bestimmten Anzahl von Fehlversuchen obligatorisch zu machen.

Advertisement
<?php

namespace app\models;

use Yii;
use yii\base\Model;

class LoginForm extends Model
{
    public $username;
    public $password;
    public $rememberMe = true;
    public $verifyCode; // Neue Eigenschaft für CAPTCHA

    // ... bestehender Code ...

    public function rules()
    {
        return [
            // Regeln für Benutzername und Passwort
            [['username', 'password'], 'required'],
            ['rememberMe', 'boolean'],
            ['password', 'validatePassword'],

            // CAPTCHA-REGELN: Nur erforderlich, wenn loginFailed true ist
            ['verifyCode', 'required', 'when' => function($model) {
                return $model->loginFailed;
            }, 'message' => 'Der CAPTCHA-Code ist nach mehreren Fehlversuchen erforderlich.'],
            ['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)) {
                // KERNLOGIK: Fehlversuchs-Zähler erhöhen
                $attempts = Yii::$app->session->get('_loginAttempts', 0) + 1;
                Yii::$app->session->set('_loginAttempts', $attempts);

                $this->addError($attribute, 'Falscher Benutzername oder Passwort.');
            } else {
                // Zähler bei erfolgreicher Anmeldung zurücksetzen
                Yii::$app->session->remove('_loginAttempts');
            }
        }
    }

    // Getter zur Überprüfung des Fehlerstatus
    public function getLoginFailed()
    {
        // CAPTCHA wird nach 3 oder mehr Fehlversuchen ausgelöst
        return Yii::$app->session->get('_loginAttempts', 0) >= 3;
    }

    // ... getUser()-Methode und andere ...
}

Schlüsselerklärung zum Code:

  • Die Eigenschaft $verifyCode speichert die CAPTCHA-Eingabe des Benutzers.
  • Die Methode getLoginFailed() prüft die Session-Variable _loginAttempts. Sie gibt true zurück, wenn Fehlversuche ≥ 3 sind.
  • Der Parameter 'when' stellt sicher, dass die Regeln für verifyCode nur gelten, wenn loginFailed true ist.

Schritt 2: CAPTCHA in der Login-View anzeigen

Passen Sie als Nächstes die Login-View-Datei an, damit das CAPTCHA-Widget nur angezeigt wird, wenn die Bedingung $model->loginFailed erfüllt ist.

Advertisement
<?php

use yii\helpers\Html;
use yii\bootstrap5\ActiveForm; // oder yii\widgets\ActiveForm

/* @var $this yii\web\View */
/* @var $form yii\widgets\ActiveForm */
/* @var $model app\models\LoginForm */

$this->title = 'Anmeldung';
?>
<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() ?>

                <!-- BEDINGTER CAPTCHA-BEREICH -->
                <?php if ($model->loginFailed): ?>
                    <div class="alert alert-warning">
                        Zu viele fehlgeschlagene Anmeldeversuche. Bitte bestätigen Sie, dass Sie ein Mensch sind.
                    </div>
                    <?= $form->field($model, 'verifyCode')->widget(\yii\captcha\Captcha::className()) ?>
                <?php endif; ?>

                <div class="form-group">
                    <?= Html::submitButton('Anmelden', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
                </div>

            <?php ActiveForm::end(); ?>
        </div>
    </div>
</div>

Schritt 3: CAPTCHA-Action im Controller konfigurieren

Das CAPTCHA-Widget benötigt eine dedizierte Action im Controller. Stellen Sie sicher, dass die ‚captcha‘-Action in `SiteController` konfiguriert ist.

<?php

namespace app\controllers;

use yii\web\Controller;

class SiteController extends Controller
{
    // ... andere actions() ...

    public function actions()
    {
        return [
            'error' => ['class' => 'yii\web\ErrorAction'],
            // DIE CAPTCHA-ACTION MUSS VORHANDEN SEIN
            'captcha' => [
                'class' => 'yii\captcha\CaptchaAction',
                'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
                'minLength' => 4,
                'maxLength' => 5,
                'offset' => 2,
                'testLimit' => 1,
            ],
            // ... andere Actions ...
        ];
    }

    // ... actionLogin() und andere Methoden ...
}

Wichtige Hinweise & zusätzliche Sicherheit

  • Session-basiert: Diese Implementierung nutzt PHP-Sessions. Stellen Sie eine sichere Konfiguration sicher.
  • Nicht die einzige Lösung: CAPTCHA sollte mit anderen Maßnahmen kombiniert werden:
    1. Ratenbegrenzung (Rate Limiting): Nutzen Sie Komponenten wie `yiifiltersRateLimiter`.
    2. Starke Passwörter: Erzwingen Sie komplexe Passwörter.
    3. Protokollierung: Protokollieren Sie alle Anmeldeversuche.
  • Zähler zurücksetzen: Der Zähler wird bei erfolgreicher Anmeldung zurückgesetzt. Eine zeitbasierte Zurücksetzung ist ebenfalls möglich.

Durch die Implementierung dieses bedingten CAPTCHAs fügen Sie eine wichtige Sicherheitsebene hinzu, die den automatisierten Ablauf von Brute-Force-Angriffen intelligent unterbricht, bei gleichbleibender Benutzerfreundlichkeit.

Neueste Artikel