身份validation2个不同的表
我需要创build一个新的“auth”configuration与另一个表和用户。 我有一个“admin”用户表和普通用户的另一个表。
但是我怎样才能创build另一个不同configuration的Auth
实例?
您可以“模拟”一个新的Auth类。
Laravel Auth组件基本上是Illuminate\Auth\Guard
类,而这个类有一些依赖关系。
所以,基本上你必须创build一个新的卫兵class和一些门面…
<?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'); } }
…添加一个ServiceProvider
来初始化这个类,传递它的依赖关系。
<?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', ); } }
在这个服务提供商中,我举了一些如何创build“新”密码提醒组件的例子。
现在您需要创build两个新的外墙,一个用于validation,一个用于密码提示。
<?php use Illuminate\Support\Facades\Facade; class ClientAuth extends Facade { protected static function getFacadeAccessor() { return 'client.auth'; } }
和…
<?php use Illuminate\Support\Facades\Facade; class ClientPassword extends Facade { protected static function getFacadeAccessor() { return 'client.reminder'; } }
当然,对于密码提醒,您需要在数据库中创build表,才能正常工作。 在这个例子中,表名应该是client_reminders
,正如你可以在服务提供者的registerReminderDatabaseRepository
方法中看到的那样。 表格结构与原始提醒表格相同。
之后,您可以像使用Auth
类一样使用ClientAuth
。 ClientPassword
和Password
类一样。
ClientAuth::gust(); ClientAuth::attempt(array('email' => $email, 'password' => $password)); ClientPassword::remind($credentials);
不要忘记将你的服务提供者添加到app/config/app.php
文件中的服务提供者列表中。
更新:
如果您使用的是Laravel 4.1,则PasswordBroker不再需要Redirect
类。
return new PasswordBroker( $app['client.reminder.repository'], $app['client.auth.provider'], $app['mailer'], 'emails.client.reminder' // email template for the reminder );
更新2
Laravel 5.2刚刚推出了多重authentication ,所以这个版本不再需要这个了。
在尝试自己解决这个问题的时候,我发现了一个更简单的方法。 我基本上创build了一个自定义的ServiceProvider来replace默认的Auth,它作为一个Auth的工厂类,允许你为多个logintypes创build多个实例。 我也卡在一个可以在这里find的包: https : //github.com/ollieread/multiauth
这真的很简单,只需用applet / config / app.php中的AuthServiceProviderreplace为Ollieread \ Multiauth \ MultiauthServiceProvider,然后将app / config / auth.php改为如下所示:
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, ), );
现在,您可以像以前一样使用Auth,但有一点区别:
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();
它还允许您同时以多个用户typeslogin,这是我正在进行的项目的一项要求。 希望它能帮助别人。
更新 – 27/02/2014
对于那些刚刚遇到这个问题的人来说,我刚刚添加了对提醒的支持,这些提醒可以用同样的工厂风格进行访问。
好吧,我有同样的问题,这是我如何解决它:
实际上,在laravel 4中,你可以简单地在运行时改变authconfiguration,这样做就可以简单地在你的App :: beforefilter中执行以下操作:
if ($request->is('admin*')) { Config::set('auth.model', 'Admin'); }
这将使Auth组件在pipe理地址中使用pipe理员模型。 但这会导致一个新的问题,因为如果你的pipe理员和用户表中有两个用户具有相同的ID,login会话密钥是相同的,你将能够login到pipe理网站,如果你之前已经login普通用户! 所以为了使两个不同的身份validation完全独立,我做了这个诀窍:
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')); });
并将App :: before代码更改为:
if ($request->is('admin*')) { Config::set('auth.driver', 'eloquent.admin'); Config::set('auth.model', 'Admin'); }
你可以看到我创build了一个新的auth驱动程序,并在Guard类中重写了一些方法,这样就会为pipe理站点生成不同的会话密钥。 然后我更改了pipe理网站的驱动程序。 祝你好运。
我昨天遇到了同样的问题,最后我创build了一个更简单的解决scheme。
我的要求在两个不同的数据库中的2个不同的表。 一个表是pipe理员,另一个表是普通用户。 而且,每个表都有自己的散列方式。 我结束了以下(代码也可以作为Github上的要点: https : //gist.github.com/Xethron/6790029 )
创build一个新的UserProvider。 我打电话给我的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; } }
然后,我通过在我的app/start/global.php
文件的顶部添加以下几行来告诉Laravel我的UserProvider。
// 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']); });
然后,我告诉Laravel使用我的用户提供者而不是app/config/auth.php
'driver' => 'multi',
现在,当我authentication的时候,我这样做:
Auth::attempt(array( 'email' => $email, 'password' => $password, 'provider'=>'joomla' ) )
然后,这个类将使用joomlaUser模型,使用joomlaHasher,并且没有选项。如果使用另一个提供者,它将包含hasher的选项。
这门课是为我所需要的而devise的,但可以很容易地改变以适应您的需求。
PS:确保自动加载器可以findMultiUserProvider,否则它将不起作用。
我正在使用Laravel 5 native auth来处理多个用户表…
这并不难,请检查这个要点:
https://gist.github.com/danielcoimbra/64b779b4d9e522bc3373
更新:对于Laravel 5,如果你需要一个更强大的解决scheme,试试这个包:
https://github.com/sboo/multiauth
丹尼尔
- 何时通过Facebook的新Android SDK 3.0请求权限?
- Symfony2扩展DefaultAuthenticationSuccessHandler
- Django Rest框架中的用户authentication+ Angular.js Web应用程序
- 覆盖ASP.NET MVC中的授权属性
- 在不违反RESTful原则的情况下对Angular进行身份validation和授权的最佳实践?
- 如何在angularjs应用程序中实现安全(!)身份validation系统?
- 使用电子邮件地址作为用户ID有什么优点和缺点?
- 使用AngularJS进行身份validation,使用REST API WS进行会话pipe理和安全问题
- 用Angular.js拦截器捕获HTTP 401