Ankündigung

Einklappen
Keine Ankündigung bisher.

Lavarel: Login mit eigenem UserProvider

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Lavarel: Login mit eigenem UserProvider

    Hallo,

    ich möchte meine Laravel-Anwendung nur Personen zugänglich machen, die eingelogged sind, d.h. alle Requests sollen mit dem Session-Guard überprüft werden. Hat sich der Nutzer nicht angemeldet, wird er zunächst nach /login weitergeleitet. Dort soll er sich dann gegen eine externe Datenquelle authentifizieren. Anlegen oder Verändern von Nutzern soll ebensowenig möglich sein, wie Passwort zusenden oder zurücksetzen.

    Hier ist die /config/auth.php:
    PHP-Code:
    <?php
    return [
        
    'defaults' => [ 'guard' => 'web''passwords' => '', ],
        
    'guards' => [ 'web' => [ 'driver' => 'session''provider' => 'users', ], ],
        
    'providers' => [ 'users' => [ 'driver' => 'ldap''model' => App\LdapUser::class, ], ],
        
    'passwords' => [ 'users' => [ 'provider' => 'users''table' => 'password_resets''expire' => 60, ], ],
    ];
    Ich lade diesen UserProvider über die boot-Funktion im LdapAuthServiceProvider (welchen ich in /config/app.php bei providers eingetragen habe):
    PHP-Code:
    <?php
    namespace App\Providers;
    use 
    App\Providers\LdapUserProvider;
    use 
    Illuminate\Support\ServiceProvider;

    class 
    LdapAuthServiceProvider extends ServiceProvider {

      public function 
    boot()
      {
        
    $this->app['auth']->provider('ldap',function() { return new LdapUserProvider(); });
      }

      public function 
    register() { }
    }
    ?>
    Der LdapUserProvider sieht dann testweise erstmal so aus:
    PHP-Code:
    <?php
    namespace App\Providers;

    use 
    App\LdapUser;
    use 
    Illuminate\Contracts\Auth\Authenticatable;
    use 
    Illuminate\Contracts\Auth\UserProvider;

    class 
    LdapUserProvider implements UserProvider {

      
    // Testweise immer ok:
      
    public function validateCredentials(Authenticatable $user, array $credentials) { return true; }

      public function 
    retrieveById($id) { return $this->dummyUser(); }
      public function 
    retrieveByCredentials(array $credentials) { return $this->dummyUser(); }

      public function 
    retrieveByToken($identifier$token) { return new \Exception('not implemented'); }
      public function 
    updateRememberToken(Authenticatable $user$token) { return new \Exception('not implemented'); }

      
    // Hilfsfunktion zu Testzwecken
      
    protected function dummyUser() {
        
    $attributes = array(
          
    'id' => 123,
          
    'username' => 'chuckles',
          
    'password' => \Hash::make('SuperSecret'),
          
    'name' => 'Dummy User',
        );
        return new 
    LdapUser($attributes);
      }

    }
    Und hier der LdapUser:
    PHP-Code:
    <?php
    namespace App;

    use 
    Illuminate\Auth\GenericUser;

    class 
    LdapUser extends GenericUser {
    }
    Routen habe ich auch in routes/web.php. Unter anderem:
    PHP-Code:
    <?php

    Route
    ::group(['middleware' => 'auth'], function () {
        
    Route::get('/helloworld', function () {return 'Hello World!';});
    });

    Route::get('/login''LdapLoginController@showLoginForm');
    Route::post('/login''LdapLoginController@login');
    Route::get('/logout''LdapLoginController@logout');
    /helloworld sollte also zunächst auf /login umleiten. Tut es auch. Der POST-Aufruf sollte dann vom LdapLoginController übernommen werden:
    PHP-Code:
    <?php
    namespace App\Http\Controllers;

    use 
    App\Http\Controllers\Controller;
    use 
    Illuminate\Foundation\Auth\AuthenticatesUsers;

    class 
    LdapLoginController extends Controller {

        
    // Trait nutzen und einzelne Funktionen unten überschreiben.
        
    use AuthenticatesUsers;
    }
    Soweit, so gut. Irgendwie muss der Controller aber nun doch ein LdapUser-Objekt erzeugen und die Session aufmachen. Da stehe ich gerade auf dem Schlauch. Kann mir jemand einen Tipp geben? Freue mich über jeden Hinweis!


  • #2
    Die Authentifizierung/Session machst du doch in der Middleware, warum also im Controller?
    "Software is like Sex, it's best if it's free." - Linus Torvalds

    Kommentar


    • #3
      Danke!

      Also sollte AuthenticatesUsers wieder aus dem Controller raus? Sollte der LdapUserProvider dann den User liefern und die Session öffnen? Funktionen hierfür habe ich ja implementiert (s.o.), aber wenn ich auf der Login-Seite auf "submit" klicke, lande ich wieder auf der Login-Seite. Keine Ahnung, woher diese Schleife kommt.

      Kommentar


      • #4
        Ja, dazu hast du ja den UserProvider.
        Du musst ja nur den Teil implementieren, indem du den User über LDAP ausliest, ein Authenticatable Objekt daraus erstellst und dieses über die Methoden des UserProvider Interfaces (was du ja schon implementiert hast) bereitstellst.
        Das User Objekt hält dir dann Laravel.

        Außerdem sei angemerkt, dass die Methode "provider" zum Registrieren des UserProviders erst ab Version 5.2 existiert. Zuvor wurde "extends" verwendet.
        Zudem solltest du auch die Methode authenticated aus dem Trait AuthenticatesUsers implementieren, da diese im Trait leer ist.

        Was sagt denn das Debugging wo evtl. Fehler auftreten?

        Btw. gibt es für Laravel schon eine fertige LDAP Authentication Library: https://github.com/Adldap2
        "Software is like Sex, it's best if it's free." - Linus Torvalds

        Kommentar


        • #5
          Warum so kompliziert?
          Du kannst doch ein Auth aufsetzen:

          PHP-Code:
            php artisan make:auth 
          https://laravel.com/docs/5.5/authentication

          Einen User registrieren und dann die Registrierung abschalten.

          Kommentar


          • #6
            Zitat von chim Beitrag anzeigen
            Warum so kompliziert?
            Weil er LDAP zur Authentifizierung nutzen möchte, was Laravel logischerweise nicht Standardmäßig macht.
            "Software is like Sex, it's best if it's free." - Linus Torvalds

            Kommentar


            • #7
              Vielen Dank für die Hinweise. Ich bin gerade mit anderen Projekten im Vorweihnachts-Endspurt, werde das aber in den nächsten Tagen wie von Dir, JaMa, in Beitrag #4 vorgeschlagen ausprobieren. Ich werde auch wie von chim vorgeschlagen, den artisan-Befehl ausführen. Allerdings in einem leeren Projekt, um mir mal anzuschauen, wie die Controller etc. dann aussehen.

              Die Adldap2-Bibliothek hatte ich mir mal angeschaut. Dagegen sprachen/sprechen folgende Gründe:
              1. Die Integration schien mir als Laravel-Neuling mindestens genauso komplex wie eine eigene Programmierung.
              2. Ich benötige ja nur einen kleinen Teil dessen, was Adldap2 bietet. Einiges, wie das Anlegen neuer Nutzer möchte ich überhaupt nicht unterstützen.
              3. Ich glaube, das Selbstschreiben (mit Eurer Hilfe) ist auch ein guter Weg, um die Prinzipien von Laravel besser zu verstehen.

              Kommentar


              • #8
                Der Artisan-Command wird dir nur Views, Routen und Controller erzeugen für die Funktionalitäten die du ohnehin nicht brauchst
                "Software is like Sex, it's best if it's free." - Linus Torvalds

                Kommentar


                • #9
                  Ich habe nun den Grund gefunden, warum ich immer wieder auf der Login-Seite gelandet bin: Da ich den trait AuthenticatesUsers genutzt habe, wurde dort intern die Funktion

                  PHP-Code:
                  public function username()
                  {
                      return 
                  'email';

                  genutzt. Dieses Feld gibt es in meinem Login-Formular jedoch nicht. Ich habe die Methode nun derart überschrieben, dass das von mir verwendete Feld als username verwendet wird. Dann geht's! Vielen Dank schon mal.

                  Fehlt jetzt noch das Überschreiben der Funktion authenticated. Ich frage mich nur, was die Methode überhaupt macht. Aus dem Kommentar "The user has been authenticated" mit Rückgabewert "mixed" werde ich leider nicht wirklich schlau.

                  Kommentar

                  Lädt...
                  X