Autenticazione con 2 tavoli diversi

Devo creare una nuova configurazione “auth” con un’altra tabella e utenti. Ho una tabella per gli utenti “admin” e un’altra tabella per gli utenti normali.

Ma come posso creare un’altra istanza di Auth con una configurazione diversa?

È ansible “emulare” una nuova class Auth.

Il componente Laravel Auth è fondamentalmente la class Illuminate\Auth\Guard e questa class ha alcune dipendenze.

Quindi, in pratica devi creare una nuova class Guard e alcune facciate …

  

... aggiungi un ServiceProvider per inizializzare questa class, passando le sue dipendenze.

 registerAuth(); $this->registerReminders(); } protected function registerAuth() { $this->registerClientCrypt(); $this->registerClientProvider(); $this->registerClientGuard(); } protected function registerClientCrypt() { $this->app['client.auth.crypt'] = $this->app->share(function($app) { return new BcryptHasher; }); } protected function registerClientProvider() { $this->app['client.auth.provider'] = $this->app->share(function($app) { return new EloquentUserProvider( $app['client.auth.crypt'], 'Client' ); }); } protected function registerClientGuard() { $this->app['client.auth'] = $this->app->share(function($app) { $guard = new Guard( $app['client.auth.provider'], $app['session.store'] ); $guard->setCookieJar($app['cookie']); return $guard; }); } protected function registerReminders() { # DatabaseReminderRepository $this->registerReminderDatabaseRepository(); # PasswordBroker $this->app['client.reminder'] = $this->app->share(function($app) { return new PasswordBroker( $app['client.reminder.repository'], $app['client.auth.provider'], $app['redirect'], $app['mailer'], 'emails.client.reminder' // email template for the reminder ); }); } protected function registerReminderDatabaseRepository() { $this->app['client.reminder.repository'] = $this->app->share(function($app) { $connection = $app['db']->connection(); $table = 'client_reminders'; $key = $app['config']['app.key']; return new DatabaseReminderRepository($connection, $table, $key); }); } public function provides() { return array( 'client.auth', 'client.auth.provider', 'client.auth.crypt', 'client.reminder.repository', 'client.reminder', ); } } 

In questo fornitore di servizi, ho inserito alcuni esempi su come creare un nuovo componente per il promemoria della password.

Ora è necessario creare due nuove facciate, una per l'autenticazione e una per i promemoria della password.

  

e...

  

Ovviamente, per i promemoria delle password, è necessario creare la tabella nel database, per poter funzionare. In questo esempio, il nome della tabella deve essere client_reminders , come si può vedere nel metodo registerReminderDatabaseRepository nel provider di servizi. La struttura della tabella è uguale alla tabella dei promemoria originali.

Successivamente, puoi utilizzare ClientAuth nello stesso modo in cui utilizzi la class Auth . E la stessa cosa per ClientPassword con la class Password .

 ClientAuth::gust(); ClientAuth::attempt(array('email' => $email, 'password' => $password)); ClientPassword::remind($credentials); 

Non dimenticare di aggiungere il tuo fornitore di servizi all'elenco dei fornitori di servizi nel file app/config/app.php .

AGGIORNARE:

Se si utilizza Laravel 4.1, PasswordBroker non ha più bisogno della class Redirect .

 return new PasswordBroker( $app['client.reminder.repository'], $app['client.auth.provider'], $app['mailer'], 'emails.client.reminder' // email template for the reminder ); 

AGGIORNAMENTO 2

Laravel 5.2 ha appena introdotto multi auth , quindi non è più necessario in questa versione.

Mentre cercavo di risolvere da solo questo problema, ho trovato un modo molto più semplice. Fondamentalmente ho creato un ServiceProvider personalizzato per sostituire quello predefinito Auth, che funge da class di produzione per Auth e consente di avere più istanze per più tipi di accesso. Ho anche bloccato tutto in un pacchetto che può essere trovato qui: https://github.com/ollieread/multiauth

È davvero facile da usare davvero, basta sostituire AuthServiceProvider in app / config / app.php con Ollieread \ Multiauth \ MultiauthServiceProvider, quindi cambiare app / config / auth.php per assomigliare a qualcosa del genere:

 return array( 'multi' => array( 'account' => array( 'driver' => 'eloquent', 'model' => 'Account' ), 'user' => array( 'driver' => 'database', 'table' => 'users' ) ), 'reminder' => array( 'email' => 'emails.auth.reminder', 'table' => 'password_reminders', 'expire' => 60, ), ); 

Ora puoi usare Auth allo stesso modo di prima, ma con una leggera differenza:

 Auth::account()->attempt(array( 'email' => $attributes['email'], 'password' => $attributes['password'], )); Auth::user()->attempt(array( 'email' => $attributes['email'], 'password' => $attributes['password'], )); Auth::account()->check(); Auth::user()->check(); 

Permette anche di accedere come più tipi di utenti contemporaneamente, che era un requisito per un progetto su cui stavo lavorando. Spero che aiuti qualcuno oltre a me.

AGGIORNAMENTO – 27/02/2014

Per quelli di voi che hanno appena trovato questa risposta, recentemente ho aggiunto il supporto per i promemoria, a cui è ansible accedere nello stesso modo in cui sono stati creati in fabbrica.

Ok, ho avuto lo stesso problema ed ecco come ho risolto:

in realtà in laravel 4 puoi semplicemente modificare le configurazioni di auth in fase di esecuzione, in modo da fare il trucco puoi semplicemente fare quanto segue nella tua App :: before filter:

 if ($request->is('admin*')) { Config::set('auth.model', 'Admin'); } 

questo farà sì che il componente Auth utilizzi il modello Admin quando si trova in URL di amministrazione. ma questo porterà a un nuovo problema, perché la chiave della sessione di accesso è la stessa se si hanno due utenti nella tabella degli amministratori e degli utenti con lo stesso id che sarà in grado di accedere al sito admin se si è effettuato il login prima come utente normale! quindi per rendere le due diverse autenticazioni completamente indipendenti ho fatto questo trucco:

 class AdminGuard extends Guard { public function getName() { return 'admin_login_'.md5(get_class($this)); } public function getRecallerName() { return 'admin_remember_'.md5(get_class($this)); } } Auth::extend('eloquent.admin', function() { return new AdminGuard(new EloquentUserProvider(new BcryptHasher, 'Admin'), App::make('session.store')); }); 

e cambia l’App :: before code in:

 if ($request->is('admin*')) { Config::set('auth.driver', 'eloquent.admin'); Config::set('auth.model', 'Admin'); } 

puoi vedere che ho creato un nuovo driver auth e ho riscritto alcuni metodi sulla class Guard in modo da generare diverse chiavi di sessione per il sito admin. poi ho cambiato il driver per il sito admin. in bocca al lupo.

Ho avuto lo stesso problema ieri, e ho finito per creare una soluzione molto più semplice.

Le mie esigenze in cui 2 diverse tabelle in due database diversi. Un tavolo era per gli amministratori, l’altro era per gli utenti normali. Inoltre, ogni tavolo aveva il suo modo di fare hashing. Ho finito con il seguente (Codice disponibile anche come sintesi su Github: https://gist.github.com/Xethron/6790029 )

Crea un nuovo UserProvider. Ho chiamato il mio MultiUserProvider.php

 providers = array( 'joomla' => array( 'model' => 'JoomlaUser', 'hasher' => 'JoomlaHasher', ) 'another' => array( 'model' => 'AnotherUser', 'hasher' => 'AnotherHasher', 'options' => array( 'username' => 'empolyee_number', 'salt' => 'salt', ) ), ); } /** * Retrieve a user by their unique identifier. * * @param mixed $identifier * @return \Illuminate\Auth\UserInterface|null */ public function retrieveById($identifier) { // Returns the current provider from the session. // Should throw an error if there is none... $provider = Session::get('user.provider'); $user = $this->createModel($this->providers[$provider]['model'])->newQuery()->find($identifier); if ($user){ $user->provider = $provider; } return $user; } /** * Retrieve a user by the given credentials. * * @param array $credentials * @return \Illuminate\Auth\UserInterface|null */ public function retrieveByCredentials(array $credentials) { // First we will add each credential element to the query as a where clause. // Then we can execute the query and, if we found a user, return it in a // Eloquent User "model" that will be utilized by the Guard instances. // Retrieve the provider from the $credentials array. // Should throw an error if there is none... $provider = $credentials['provider']; $query = $this->createModel($this->providers[$provider]['model'])->newQuery(); foreach ($credentials as $key => $value) { if ( ! str_contains($key, 'password') && ! str_contains($key, 'provider')) $query->where($key, $value); } $user = $query->first(); if ($user){ Session::put('user.provider', $provider); $user->provider = $provider; } return $user; } /** * Validate a user against the given credentials. * * @param \Illuminate\Auth\UserInterface $user * @param array $credentials * @return bool */ public function validateCredentials(UserInterface $user, array $credentials) { $plain = $credentials['password']; // Retrieve the provider from the $credentials array. // Should throw an error if there is none... $provider = $credentials['provider']; $options = array(); if (isset($this->providers[$provider]['options'])){ foreach ($this->providers[$provider]['options'] as $key => $value) { $options[$key] = $user->$value; } } return $this->createModel($this->providers[$provider]['hasher']) ->check($plain, $user->getAuthPassword(), $options); } /** * Create a new instance of a class. * * @param string $name Name of the class * @return Class */ public function createModel($name) { $class = '\\'.ltrim($name, '\\'); return new $class; } } 

Poi, ho detto a Laravel del mio UserProvider aggiungendo le seguenti righe all’inizio del mio file app/start/global.php .

 // app/start/global.php // Add the following few lines to your global.php file Auth::extend('multi', function($app) { $provider = new \MultiUserProvider(); return new \Illuminate\Auth\Guard($provider, $app['session']); }); 

E poi, ho detto a Laravel di usare il mio provider di utenti invece di EloquentUserProvider in app/config/auth.php

 'driver' => 'multi', 

Ora, quando effettuo l’autenticazione, lo faccio così:

 Auth::attempt(array( 'email' => $email, 'password' => $password, 'provider'=>'joomla' ) ) 

La class userebbe quindi il modello joomlaUser, con joomlaHasher e nessuna opzione per l’hasher … Se si utilizza un “altro” provider, includerà le opzioni per l’hasher.

Questa class è stata costruita per quello che ho richiesto, ma può essere facilmente modificata per soddisfare le tue esigenze.

PS: assicurati che il caricatore automatico trovi MultiUserProvider, altrimenti non funzionerà.

Sto usando l’autenticazione nativa di Laravel 5 per gestire più tabelle utente …

Non è difficile, per favore controlla questo Gist:

https://gist.github.com/danielcoimbra/64b779b4d9e522bc3373

AGGIORNAMENTO: per Laravel 5, se hai bisogno di una soluzione più robusta, prova questo pacchetto:

https://github.com/sboo/multiauth

Daniel