Rezepte für Nginx: LDAP-Authentifizierung mit CAPTCHA

Für die Authentifizierung mit Captcha benötigen wir selbst nginx und seine Plugins encrypted-session, form-input, ctpp2, echo, ldap, headers-more, auth_request, set-misc. (Ich habe Links zu meinen Forks bereitgestellt, da ich einige Änderungen vorgenommen habe, die ich bisher nicht in die ursprünglichen Repositories einbringen konnte. Man kann auch auf ein fertiges Bild zurückgreifen.)

Zunächst definieren wir

encrypted_session_key "abcdefghijklmnopqrstuvwxyz123456";

Als nächstes schalten wir vorsichtshalber den Authentifizierungsheader aus

more_clear_input_headers Authorization;

Jetzt sichern wir alles mit einer Authentifizierung

auth_request /auth;
location =/auth {
    internal;
    subrequest_access_phase on; # Erlaube Autorisierungsphase im Unterantrag
    auth_request off; # keine Autorisierung verwenden
    set_decode_base64 $auth_decode $cookie_auth; # dekodiere das Authentifizierungs-Cookie
    set_decrypt_session $auth_decrypt $auth_decode; # entschlüssle die Authentifizierung
    if ($auth_decrypt = "") { return 401 UNAUTHORIZED; } # wenn die Entschlüsselung fehlschlägt, ist der Benutzer nicht autorisiert
    more_set_input_headers "Authorization: Basic $auth_decrypt"; # setze die Authentifizierung auf Basic (zum Nutzen der Variable $remote_user)
    auth_basic_ldap_realm Auth; # LDAP-Authentifizierung aktivieren
    auth_basic_ldap_url ldap://ldap.server.com; # Adresse festlegen
    auth_basic_ldap_bind_dn dn.server.com; # Postfix festlegen
    echo -n OK; # Benutzer autorisiert
}

Für autorisierte Benutzer zeigen wir Inhalte aus ihrem Verzeichnis an.

location /{
    alias html/$remote_user/;
}

Im Falle fehlender Authentifizierung zeigen wir das Anmeldeformular mit CAPTCHA an.

error_page 401 = @error401;
location @error401 {
    set_escape_uri $request_uri_escape $request_uri; # Anfrage kodieren
    return 303 /login?request_uri=$request_uri_escape; # Weiterleitung zur Anmeldeseite mit Captcha, Anfrage beibehalten
}
location = /login {
    default_type "text/html; charset=utf-8"; # Typ festlegen
    if ($request_method = GET) { # Wenn nur die Anmeldeseite mit Captcha angezeigt werden soll
        template login.html.ct2; # Vorlage festlegen
        ctpp2 on; # Template-Engine aktivieren
        set_secure_random_alphanum $csrf_random 32; # Zufälliges CSRF festlegen
        encrypted_session_expires 300; # Lebensdauer des CSRF auf 5 Minuten setzen (5 * 60 = 300)
        set_encrypt_session $csrf_encrypt $csrf_random; # Zufälliges CSRF verschlüsseln
        set_encode_base64 $csrf_encode $csrf_encrypt; # Verschlüsseltes CSRF kodieren
        add_header Set-Cookie "CSRF=$csrf_encode; Max-Age=300"; # Verschlüsseltes CSRF in ein Cookie für 5 Minuten ablegen (5 * 60 = 300)
        return 200 "{"csrf":"$csrf_random"}"; # JSON für Template-Engine zurückgeben
    } # ansonsten - Anmeldeseite mit Captcha verarbeiten
    set_form_input $csrf_form csrf; # CSRF aus dem Formular erhalten
    set_unescape_uri $csrf_unescape $csrf_form; # CSRF aus dem Formular dekodieren
    set_decode_base64 $csrf_decode $cookie_csrf; # CSRF aus dem Cookie dekodieren
    set_decrypt_session $csrf_decrypt $csrf_decode; # CSRF aus dem Cookie entschlüsseln
    if ($csrf_decrypt != $csrf_unescape) { return 303 $request_uri; } # Wenn CSRF aus dem Formular nicht mit CSRF im Cookie übereinstimmt, zurück zur Formularanzeige umleiten
    set_form_input $captcha_form captcha; # Captcha aus dem Formular erhalten
    set_unescape_uri $captcha_unescape $captcha_form; # Captcha aus dem Formular dekodieren
    set_md5 $captcha_md5 "secret${captcha_unescape}${csrf_decrypt}"; # MD5 berechnen
    if ($captcha_md5 != $cookie_captcha) { return 303 $request_uri; } # Wenn MD5 nicht mit dem Captcha im Cookie übereinstimmt, zurück zur Formularanzeige umleiten
    set_form_input $username_form username; # Benutzername aus dem Formular erhalten
    set_form_input $password_form password; # Passwort aus dem Formular erhalten
    set_unescape_uri $username_unescape $username_form; # Benutzername aus dem Formular dekodieren
    set_unescape_uri $password_unescape $password_form; # Passwort aus dem Formular dekodieren
    encrypted_session_expires 2592000; # Lebensdauer der Sitzung auf 30 Tage festlegen (30 * 24 * 60 * 60 = 2592000)
    set $username_password "$username_unescape:$password_unescape"; # Basic-Authentifizierung festlegen
    set_encode_base64 $username_password_encode $username_password; # Basic-Authentifizierung kodieren
    set_encrypt_session $auth_encrypt $username_password_encode; # Basic-Authentifizierung verschlüsseln
    set_encode_base64 $auth_encode $auth_encrypt; # Verschlüsselte Basic-Authentifizierung kodieren
    add_header Set-Cookie "Auth=$auth_encode; Max-Age=2592000"; # Verschlüsselte Basic-Authentifizierung in ein Cookie für 30 Tage ablegen (30 * 24 * 60 * 60 = 2592000)
    set $arg_request_uri_or_slash $arg_request_uri; # Anfrage aus den Argumenten kopieren
    set_if_empty $arg_request_uri_or_slash "/"; # Wenn kein Argument angegeben ist, zum Beginn
    set_unescape_uri $request_uri_unescape $arg_request_uri_or_slash; # Anfrage dekodieren
    return 303 $request_uri_unescape; # Auf die gespeicherte Anfrage umleiten
}

login.html

<html>
    <body>
        <form method="post" action="">
            <input type="hidden" name="csrf" value="<TMPL_var csrf>" />
            Benutzername: <input type="text" name="username" placeholder="Benutzernamen eingeben..." /><br />
            password: <input type="password" name="password" /><br />
            Captcha: <img src="/captcha?csrf=<TMPL_var csrf>"/><input type="text" name="captcha" autocomplete="off" /><br />
            <input type="submit" name="submit" value="Absenden" />
        <input type="hidden" name="trp-form-language" value="de"/></form>
    </body>
</html>

Quelle: habr.com

Kaufen Sie zuverlässiges Hosting für Websites mit DDoS-Schutz, VPS VDS-Server 🔥 Kaufen Sie zuverlässiges Hosting für Websites mit DDoS-Schutz, VPS VDS-Server | ProHoster