Autenticação com 2 tabelas diferentes

Eu preciso criar uma nova configuração “auth” com outra tabela e usuários. Eu tenho uma tabela para os usuários “admin” e outra tabela para os usuários normais.

Mas como posso criar outra instância de Auth com uma configuração diferente?

Você pode “emular” uma nova class Auth.

O componente Laravel Auth é basicamente a class Illuminate\Auth\Guard , e essa class tem algumas dependencies.

Então, basicamente você tem que criar uma nova class Guard e algumas fachadas …

  

... adicione um ServiceProvider para inicializar esta class, passando suas dependencies.

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

Neste Service Provider, eu coloquei um exemplo de como criar um 'novo' lembrete de senha para o.

Agora você precisa criar duas novas fachadas, uma para autenticação e outra para lembretes de senha.

  

e...

  

Claro, para lembretes de senha, você precisa criar a tabela no database, para funcionar. Neste exemplo, o nome da tabela deve ser client_reminders , como você pode ver no método registerReminderDatabaseRepository no Service Provider. A estrutura da tabela é a mesma da tabela original de lembretes.

Depois disso, você pode usar seu ClientAuth da mesma forma que usa a class Auth . E a mesma coisa para o ClientPassword com a class Password .

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

Não se esqueça de adicionar seu provedor de serviços à lista de provedores de serviços no arquivo app/config/app.php .

ATUALIZAR:

Se você estiver usando o Laravel 4.1, o PasswordBroker não precisa mais da class Redirect .

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

ATUALIZAÇÃO 2

O Laravel 5.2 acaba de introduzir o multi auth , então isso não é mais necessário nesta versão.

Ao tentar resolver este problema, encontrei uma maneira muito mais simples. Eu basicamente criei um ServiceProvider personalizado para replace o padrão Auth, que serve como uma class de fábrica para Auth, e permite que você tenha várias instâncias para vários tipos de login. Eu também coloquei tudo em um pacote que pode ser encontrado aqui: https://github.com/ollieread/multiauth

É muito fácil de usar, apenas substitua o AuthServiceProvider em app / config / app.php pelo Ollieread \ Multiauth \ MultiauthServiceProvider, e altere app / config / auth.php para algo parecido com isto:

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

Agora você pode usar o Auth da mesma maneira que antes, mas com uma pequena diferença:

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

Ele também permite que você faça login simultaneamente como vários tipos de usuários, o que era um requisito para um projeto no qual eu estava trabalhando. Espero que ajude alguém que não seja eu.

ATUALIZAÇÃO – 27/02/2014

Para aqueles de vocês que estão encontrando essa resposta, recentemente adicionamos suporte a lembretes, que podem ser acessados ​​da mesma maneira no estilo de fábrica.

Ok, eu tive o mesmo problema e aqui está como eu resolvi isso:

na verdade, em laravel 4, você pode simplesmente alterar as configurações de autenticação em tempo de execução, para fazer o truque, basta fazer o seguinte em seu filtro App :: before:

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

isso fará com que o componente Auth use o modelo Admin quando estiver em URLs de administrador. mas isso levará a um novo problema, porque a chave de session de login é a mesma se você tiver dois usuários em sua tabela de administradores e usuários com o mesmo ID, você poderá acessar o site admin se já tiver efetuado login como um usuário regular! então para fazer as duas autenticações diferentes completamente independentes eu fiz esse truque:

 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 mude o código App :: before para:

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

você pode ver que eu criei um novo driver de autenticação e reescrevi alguns methods na class Guard para gerar diferentes chaves de session para o site admin. então eu mudei o driver para o site admin. boa sorte.

Eu tive o mesmo problema ontem e acabei criando uma solução muito mais simples.

Meus requisitos, onde duas tabelas diferentes em dois bancos de dados diferentes. Uma tabela era para administradores, a outra era para usuários normais. Além disso, cada tabela tinha seu próprio modo de hashing. Eu terminei com o seguinte (Código também disponível como uma essência no Github: https://gist.github.com/Xethron/6790029 )

Crie um novo UserProvider. Eu chamei o meu 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; } } 

Então, eu disse ao Laravel sobre o meu UserProvider adicionando as seguintes linhas no topo do meu arquivo 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 então, eu disse ao Laravel para usar meu provedor de usuário em vez do EloquentUserProvider em app/config/auth.php

 'driver' => 'multi', 

Agora, quando eu autentico, eu faço assim:

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

A class usaria então o modelo joomlaUser, com o joomlaHasher, e nenhuma opção para o hasher … Se estiver usando o ‘outro’ provedor, ele includeá opções para o hasher.

Essa class foi criada para o que eu precisava, mas pode ser facilmente alterada para atender às suas necessidades.

PS: Certifique-se de que o autoloader pode encontrar MultiUserProvider, senão não funcionará.

Estou usando a autenticação nativa do Laravel 5 para lidar com várias tabelas de usuários …

Não é difícil, por favor, verifique esta essência:

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

ATUALIZAÇÃO: Para o Laravel 5, se você precisa de uma solução mais robusta, experimente este pacote:

https://github.com/sboo/multiauth

Daniel