Autenticación con 2 tablas diferentes


Necesito crear una nueva configuración "auth" con otra tabla y usuarios. Tengo una tabla para los usuarios" admin " y otra tabla para los usuarios normales.

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

Author: giannis christofakis, 2013-09-13

5 answers

Puede "emular" una nueva clase 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 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 'nuevo' componente de recordatorio de contraseña.

Ahora necesita crear dos nuevas fachadas, uno para autenticación y otro para recordatorios de contraseñas.

<?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 los recordatorios de contraseñas, debe crear la tabla en la base de datos, con el fin de trabajar. En este ejemplo, el nombre de la tabla debe ser client_reminders, como se puede ver en el método registerReminderDatabaseRepository en el Proveedor de servicios. La estructura de la tabla es la misma que la tabla recordatorios original.

Después de eso, puedes usar tu ClientAuth de la misma manera que usas la clase Auth. Y lo mismo para ClientPassword con el Password clase.

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.

ACTUALIZACIÓN:

Si está utilizando Laravel 4.1, el 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 introducir multi auth, por lo que esto ya no es necesario en esta versión.

 15
Author: Luis Dalmolin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-21 10:50:59

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 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 me metió todo en un paquete que se puede encontrar aquí: https://github.com/ollieread/multiauth

Es bastante fácil de usar realmente, simplemente reemplace el AuthServiceProvider en app/config/app.php con Ollieread\Multiauth\MultiauthServiceProvider, luego cambie app/config / auth.php para ver algo como esto:

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 ligera 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 que era un requisito para un proyecto en el que estaba trabajando. Espero que ayude a alguien que no sea yo.

ACTUALIZAR - 27/02/2014

Para aquellos de ustedes que acaban de venir a través de este respuesta, recientemente he agregado soporte para recordatorios, a los que se puede acceder de la misma manera de fábrica.

 31
Author: ollieread,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-27 16:02:44

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

En realidad, en laravel 4, simplemente puede cambiar las configuraciones de autenticación en tiempo de ejecución, por lo que para hacer el truco, simplemente puede hacer lo siguiente en su 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 de administración. pero esto conducirá a un nuevo problema, porque la clave de sesión de inicio de sesión es la misma si tiene dos usuarios en su tabla administradores y usuarios con el mismo id al que podrá iniciar sesión el sitio de administración si ha iniciado sesión antes como usuario regular! así que para hacer las dos authetications diferentes 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 cambia el código App:: before a:

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

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

 12
Author: Amir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-12 06:21:14

Tuve el mismo problema ayer, y terminé creando una solución mucho más simple.

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

Crea un nuevo UserProvider. Yo llamé al mío 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;
    }

}

Entonces, Yo le conté a Laravel sobre mi UserProvider agregando las siguientes líneas a la parte superior de mi archivo 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 usara 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 entonces usaría el modelo joomlaUser, con el joomlaHasher, y ninguna opción para el hasher... Si usa' otro ' proveedor, incluirá opciones para el hasher.

Esta clase fue construida para lo que yo requerido, pero se puede cambiar fácilmente para adaptarse a sus necesidades.

PD: Asegúrese de que el cargador automático pueda encontrar MultiUserProvider, de lo contrario no funcionará.

 3
Author: Xethron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-02 14:50:39

Estoy usando Laravel 5 native auth para manejar varias tablas de usuarios...

No es difícil, por favor, compruebe esta esencia:

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

 1
Author: Daniel Cintra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-20 18:43:40