An old door with an rusty lock on it
Felogin mit rsaauth auf jeder Seite

Eigenes Partial und ein paar Zeilen Javascript

Felogin Form mit rsaauth auf jeder Seite

Einbinden eines eigenen Login-Formulars für felogin mit rsaauth per Partial auf allen Seiten einer TYPO3 Installation.

Ausgangssituation

Ich arbeite gerade an einer neuen Homepage auf TYPO3 7.6.11 Basis, die auf jeder Seite ein Login Formular haben soll, wenn der Frontenduser noch nicht eingeloggt ist. Bereits eingeloggten Benutzern wird an der selben Stelle ein erweitertes Benutzermenü angezeigt.

Dazu habe ich zunächst ganz normal und nach Anleitung die System Extension felogin eingerichtet und eine Login Seite mit dem felogin Plugin angelegt. Zusätzlich ist die rsaauth System extension installiert und aktiviert, damit Frontend und Backend-Passwörter verschlüsselt übertragen werden.

Natürlich habe ich zunächst mal gesucht, was es schon gibt. Interessant sah zunächst die ajaxlogin Extension aus, die auf typo3.org verwendet wird. Aber: kein composer.json und keine Verwendung von Namespaces? meh. Da muss was eigenes her und das muss doch einfacher gehen. Eine gute Stunde später hatte ich dann die folgende Lösung gefunden.

Login Form auf jeder Seite

Um das Login Form (oder für eingeloggte User das Benutzermenü) auf jeder Seite anzuzeigen wird das folgende Partial verwendet, das im Template an entsprechender Stelle im Header eingebunden wird:

{namespace v=FluidTYPO3\Vhs\ViewHelpers}
<v:variable.set name="userLoginPID" value="{v:variable.typoscript(path: 'site.pid.userLogin')}"/>
<v:variable.set name="userRegisterPID" value="{v:variable.typoscript(path: 'site.pid.userRegister')}"/>
<f:security.ifAuthenticated>
 <f:then>
 Hallo {username}!
 <form class="user-login-header" action="{f:uri.page(pageUid: userLoginPID)}" target="_top" method="post">
 <fieldset>
 <legend>Abmelden</legend>
 <div>
 <input class="btn btn-default btn-fullwidth" type="submit" name="submit" value="Abmelden">
 </div>

 <div class="felogin-hidden">
 <input type="hidden" name="logintype" value="logout">
 <input type="hidden" name="pid" value="{userLoginPID}">
 <input type="hidden" name="redirect_url" value="{f:uri.page()}">
 </div>
 </fieldset>
 </form>
 </f:then>
 <f:else>
 <script type="text/javascript">
 var rsaScriptUrl = '{f:uri.resource(path: "JavaScript/RsaEncryptionWithLib.min.js", extensionName: "rsaauth", absolute: 1)}';
 function rsaauthInit() {
 if (typeof TYPO3RsaEncryptionPublicKeyUrl == 'undefined') {
 console.log("loading rsa stuff");
 // load rsauth js
 var script = document.createElement('script');
 script.src = rsaScriptUrl;
 script.onload = function () {
 // make sure RSAEncrypt function exists now and set TYPO3RsaEncryptionPublicKeyUrl
 if (typeof RSAEncrypt === 'function') {
 TYPO3RsaEncryptionPublicKeyUrl = '?eID=RsaPublicKeyGenerationController';
 } else {
 console.error("There was an error loading RsaEncryptionWithLib, Login will not work.");
 console.error(rsaScriptUrl + " could not be loaded or does not contain the needed functions.");
 }
 };
 document.head.appendChild(script);
 }
 }
 </script>
 <div class="col-xs-12">
 <p>Einloggen oder einen
 <f:link.page pageUid="{userRegisterPID}">neuen Benutzer registrieren.</f:link.page>
 </p>
 </div>
 <form class="user-login-header" action="{f:uri.page(pageUid: userLoginPID)}" target="_top" method="post"
 onsubmit="return true;">
 <div class="form-group row">
 <div class="col-xs-6">
 <input class="form-control" type="text" id="user" name="user" placeholder="Benutzer" value="">
 </div>
 <div class="col-xs-6">
 <input class="form-control" type="password" id="pass" name="pass" value="" data-rsa-encryption
 onfocus="rsaauthInit()" placeholder="Passwort">
 </div>
 </div>
 <div class="row">
 <div class="col-xs-12">
 <input class="btn btn-default btn-fullwidth" type="submit" name="submit" value="Anmelden">
 </div>
 </div>

 <div class="felogin-hidden">
 <input type="hidden" name="logintype" value="login">
 <input type="hidden" name="pid" value="{userLoginPID}">
 <input type="hidden" name="redirect_url" value="{f:uri.page()}">

 </div>
 </form>
 </f:else>

</f:security.ifAuthenticated>

Hinweise zum Partial

  • Zeile 1 Hinzufügen des Namespace für die vhs extension
  • Zeilen 2-3 Setzen der beiden Variablen userLoginPid und UserRegisterPid, die wir später benötigen. Dazu sind die Page IDs der beiden Seiten im Typoscript gesetzt.
  • Zeile 4 mit dem f:security:ifAuthenticated Viewhelper wird zwischen eingeloggten und noch nicht eingeloggten Benutzern unterschieden, diese Erhalten eine unterschiedliche Ausgabe.
  • Zeilen 7-20 Formular zum ausloggen für eingeloggte Benutzer.
  • Zeilen 23-43 Inline Javascript um herauszufinden, ob das benötigte Skript für rsaauth bereits geladen ist. Ansonsten wird das jetzt vorbereitet. Geladen wird das Script jedoch erst, sobald der Benutzer das Passwort-Feld fokussiert. Indem das Script erst dann geladen wird, werden eine Menge unnötiger Ajax-Requests um den Public Key für die RSA verschlüsselung zu holen eingespart. Ausserdem wird durch diese Abfrage sichergestellt, dass das Skript nicht ausgeführt wird, wenn die aktuelle Seite das Skript bereits geladen hat und der Public Key schon zur Verfügung steht.
  • Zeilen 44-71 Ein eigenes Login Formular mit der userLoginPID-Seite als action.
  • Zeile 56 Das Passwortfeld muss erweitert werden um data-rsa-encryption und onfocus="rsaauthInit()", um das rsaauth script zu laden, sobald das Feld den Fokus erhält.

Kommentare (6)

  1. Albi
    Albi am 20.02.2017
    [Schild ignorierend]
    Gute Idee, danke.
    Muss man beim Einbinden irgendwas beachten? Hier dürfte doch eigentlich nix fehlen(?):
    <f:render partial="Elements/LoginForm" arguments="{_all}" />

    Hab ich was vergessen? Kriege nur eine Fehlermeldung.
    Grüße
    Albi
    [/Schild ignorierend]
  2. Manuel
    Manuel am 20.02.2017
    Hallo Albi,

    wie Du das partial renderst sieht richtig aus. Hast du denn die richtigen Variablen für die Seiten-PIDs (Zeilen 2 und 3) korrekt gesetzt, also hast Du z.B. 'site.pid.userLogin' im Typoscript definiert irgendwo? Zu Testzwecken trage hier doch mal direkt die PIDs deiner Login /Registrierungsseiten ein. Wäre jetzt mal mein erster Verdacht, dass es daran liegt.
  3. Albi
    Albi am 21.02.2017
    Danke Manuel, es klappt jetzt. Die PIDs waren zwar per TS drin, hatte mich aber vertippt :-(
    Die Hidden-Felder zum Login musste ich bei mir noch etwas ergänzen, nun funzt es!
    Viele Grüße
    Albi
  4. Thomas
    Thomas am 07.08.2017
    Hi Manuel,

    danke für dein Snippet.
    Nachdem du die ajaxlogin von typo3.org nicht nehmen wolltest, habe ich jetzt dein Ansatz für das neue typo3.org genutzt. :)
    Nun habe ich aber das Problem, dass nach Login die Daten wie Name und Bild des Benutzers gecached werden und ich z.T. das Bild anderer Nutzer sehe.
    Hattest du das Problem auch und wenn ja, wie hast du es gelöst?

    Grüße
    Thomas
  5. Manuel
    Manuel am 07.08.2017
    Hallo Thomas,

    ne, das Problem habe ich bisher noch nicht bemerkt oder gemeldet bekommen. Was ich aber mache ist den username (mehr gebe ich da nicht aus) als *_INT Objekt anzulegen und ins Fluid-Template durchzureichen, sowas in der Art:

    lib.username = COA_INT
    lib.username {
    10 = TEXT
    10.data = TSFE:fe_user|user|username
    10.required = 1
    }
  6. Tobias
    Tobias am 16.12.2017
    Hallo Manuel,

    Deinen Beitrag finde ich super! Ich konnte ihn ganz schnell verwenden, um auf jeder Seite das Login-Formular einzubinden. Vielen Dank dafür!

    Allerdings gibt es eine kleine Einschränkung bei der Funktionsfähigkeit und ich komme nicht hinter das Geheimnis ...:
    Das Login-Formular funktioniert, wenn ich als userLoginPID die ID des Systemordners mit den Website-Benutzern angebe. Dann funktioniert allerdings die Weiterleitung nach einem Anmeldefehler nicht (z.B. bei einem falschen Passwort).
    Das Login-Formular funktioniert NICHT, wenn ich als userLoginPID die Seite mit dem Anmelde-Plugin angebe. Dafür funktioniert dann die Weiterleitung nach Anmeldefehler. Dort lande ich nämlich ständig, wenn ich Dein Formular (und nicht das Anmelde-Plugin) benutze.

    Hast Du eine Erklärung dafür? Habe ich an Deiner Anleitung irgendwas falsch verstanden?

    Viele Grüße von
    Tobias

Neuen Kommentar schreiben