Autenticación con 2 tablas diferentes

Necesito crear una nueva configuración de “autenticación” con otra tabla y usuarios. Tengo una tabla para los usuarios “admin” y otra para los usuarios normales.

¿Pero cómo puedo crear otra instancia de Auth con una configuración diferente?

Puedes “emular” una nueva clase de Auth.

El componente Laravel Auth es básicamente la clase Illuminate\Auth\Guard , y esta clase tiene algunas dependencias.

Entonces, básicamente tienes que crear una nueva clase Guard y algunas fachadas …

 < ?php use Illuminate\Auth\Guard as AuthGuard; class CilentGuard extends AuthGuard { public function getName() { return 'login_' . md5('ClientAuth'); } public function getRecallerName() { return 'remember_' . md5('ClientAuth'); } } 

... agregue un ServiceProvider de ServiceProvider para inicializar esta clase, pasando sus dependencias.

 < ?php use Illuminate\Support\ServiceProvider; use Illuminate\Auth\EloquentUserProvider; use Illuminate\Hashing\BcryptHasher; use Illuminate\Auth\Reminders\PasswordBroker; use Illuminate\Auth\Reminders\DatabaseReminderRepository; use ClientGuard; use ClientAuth; class ClientServiceProvider extends ServiceProvider { public function register() { $this->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', ); } } 

En este proveedor de servicios, pongo un ejemplo de cómo crear un componente 'nuevo' de recordatorio de contraseña.

Ahora necesita crear dos nuevas fachadas, una para autenticación y otra para recordatorios de contraseña.

 < ?php use Illuminate\Support\Facades\Facade; class ClientAuth extends Facade { protected static function getFacadeAccessor() { return 'client.auth'; } } 

y...

 < ?php use Illuminate\Support\Facades\Facade; class ClientPassword extends Facade { protected static function getFacadeAccessor() { return 'client.reminder'; } } 

Por supuesto, para recordar las contraseñas, debe crear la tabla en la base de datos para poder trabajar. En este ejemplo, el nombre de la tabla debe ser client_reminders , como puede ver en el método registerReminderDatabaseRepository en el proveedor de servicios. La estructura de la tabla es la misma que la tabla de recordatorios original.

Después de eso, puede usar su ClientAuth la misma manera que usa la clase Auth . Y lo mismo para ClientPassword con la clase Password .

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

No olvide agregar su proveedor de servicios a la lista de proveedores de servicios en el archivo app/config/app.php .

ACTUALIZAR:

Si está utilizando Laravel 4.1, PasswordBroker ya no necesita la clase Redirect .

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

ACTUALIZACIÓN 2

Laravel 5.2 acaba de presentar multi auth , por lo que ya no es necesario en esta versión.

Al tratar de resolver este problema yo mismo, encontré una manera mucho más simple. Básicamente, creé un ServiceProvider personalizado para reemplazar el Auth one predeterminado, que sirve como una clase de fábrica para Auth, y le permite tener múltiples instancias para múltiples tipos de inicio de sesión. También pegué todo en un paquete que se puede encontrar aquí: https://github.com/ollieread/multiauth

En realidad es bastante fácil de usar, simplemente reemplace AuthServiceProvider en app / config / app.php con Ollieread \ Multiauth \ MultiauthServiceProvider, luego cambie app / config / auth.php para que se vea así:

 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, ), ); 

Ahora puedes usar Auth de la misma manera que antes, pero con una pequeña diferencia:

 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(); 

También le permite iniciar sesión como múltiples tipos de usuario simultáneamente, lo cual era un requisito para un proyecto en el que estaba trabajando. Espero que ayude a alguien que no sea yo.

ACTUALIZACIÓN – 27/02/2014

Para aquellos de ustedes que se están enterando de esta respuesta, recientemente agregué soporte para recordatorios, a los que se puede acceder de la misma manera en estilo de fábrica.

Ok, tuve el mismo problema y así es como lo resolví:

De hecho, en laravel 4 puedes simplemente cambiar las configuraciones de autenticación en tiempo de ejecución para hacer el truco. Simplemente puedes hacer lo siguiente en tu aplicación :: antes del filtro:

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

esto hará que el componente Auth use el modelo Admin cuando esté en las URL administrativas. pero esto conducirá a un nuevo problema, porque la clave de la sesión de inicio de sesión es la misma si tiene dos usuarios en la tabla de administradores y usuarios con el mismo ID, podrá iniciar sesión en el sitio de administración si ha iniciado sesión anteriormente como ¡usuario regular! así que para hacer que las dos diferentes autistemas fueran completamente independientes, hice este truco:

 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')); }); 

y cambie el código App :: before a:

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

se puede ver que hice un nuevo controlador de autenticación y reescribí algunos métodos en la clase Guard para que genere claves de sesión diferentes para el sitio de administración. luego cambié el controlador para el sitio de administración. buena suerte.

Ayer tuve el mismo problema y terminé creando una solución mucho más simple.

Mis requisitos eran 2 tablas diferentes en dos bases de datos diferentes. Una mesa era para administradores, la otra era para usuarios normales. Además, cada tabla tenía su propia forma de hash. Terminé con lo siguiente (Código también disponible como esencia en Github: https://gist.github.com/Xethron/6790029 )

Crea un nuevo UserProvider. Llamé a la mía MultiUserProvider.php

 < ?php // app/libraries/MultiUserProvider.php use Illuminate\Auth\UserProviderInterface, Illuminate\Auth\UserInterface, Illuminate\Auth\GenericUser; class MultiUserProvider implements UserProviderInterface { protected $providers; public function __construct() { // This should be moved to the config later... // This is a list of providers that can be used, including // their user model, hasher class, and hasher options... $this->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; } } 

Luego, le dije a Laravel acerca de mi UserProvider al agregar las siguientes líneas en la parte superior de mi 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']); }); 

Y luego, le dije a Laravel que utilizara mi proveedor de usuario en lugar de EloquentUserProvider en app/config/auth.php

 'driver' => 'multi', 

Ahora, cuando me autentico, lo hago así:

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

La clase usaría entonces el modelo joomlaUser, con el joomlaHasher, y no tendría opciones para el hasher … Si usa ‘otro’ proveedor, incluirá opciones para el hasher.

Esta clase fue construida para lo que necesitaba pero puede cambiarse fácilmente para satisfacer sus necesidades.

PD: asegúrese de que el autocargador pueda encontrar MultiUserProvider, de lo contrario no funcionará.

Estoy usando auth autómata Laravel 5 para manejar múltiples tablas de usuario …

No es difícil, por favor revisa este Gist:

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

ACTUALIZACIÓN: para Laravel 5, si necesita una solución más robusta, pruebe este paquete:

https://github.com/sboo/multiauth

Daniel