35

我需要用另一个表和用户创建一个新的“auth”配置。我有一个“管理员”用户的表和普通用户的另一个表。

但是我怎样才能创建另一个Auth具有不同配置的实例呢?

4

5 回答 5

31

在尝试自己解决这个问题时,我找到了一种更简单的方法。我基本上创建了一个自定义的 ServiceProvider 来替换默认的 Auth 一个,它充当 Auth 的工厂类,并允许您为多种登录类型拥有多个实例。我还将它全部放在一个包中,可以在这里找到:https ://github.com/ollieread/multiauth

它真的很容易使用,只需将 app/config/app.php 中的 AuthServiceProvider 替换为 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();

它还允许您同时以多个用户类型登录,这是我正在从事的项目的要求。希望它对我以外的人有所帮助。

更新 - 27/02/2014

对于那些刚刚遇到这个答案的人,我最近添加了对提醒的支持,可以以相同的工厂样式方式访问。

于 2013-12-15T12:34:25.867 回答
16

您可以“模拟”一个新的 Auth 类。

Laravel Auth 组件基本上就是Illuminate\Auth\Guard类,这个类有一些依赖。

所以,基本上你必须创建一个新的 Guard 类和一些门面......

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

在这个服务提供者中,我举了一些例子来说明如何创建一个“新”密码提醒组件。

现在您需要创建两个新外观,一个用于身份验证,一个用于密码提醒。

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

当然,对于密码提醒,您需要在数据库中创建表才能工作。在本例中,表名应为client_reminders,正如您registerReminderDatabaseRepository在 Service Provider 中的方法中看到的那样。表结构与原始提醒表相同。

之后,您可以ClientAuth像使用类一样使用您的Auth。班级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 刚刚引入了multi auth,所以这个版本不再需要了。

于 2013-09-13T20:55:04.850 回答
12

好的,我遇到了同样的问题,这是我的解决方法:

实际上,在 laravel 4 中,您可以简单地在运行时更改身份验证配置,因此您可以在 App::before 过滤器中简单地执行以下操作:

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

这将使 Auth 组件在管理 url 中使用 Admin 模型。但这将导致一个新问题,因为如果您的 admins 和 users 表中有两个用户具有相同的 id,那么登录会话密钥是相同的,如果您之前以普通用户!所以为了使两种不同的身份验证完全独立,我做了这个技巧:

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

您可以看到我制作了一个新的身份验证驱动程序并在 Guard 类上重写了一些方法,因此它将为管理站点生成不同的会话密钥。然后我更改了管理站点的驱动程序。祝你好运。

于 2013-12-03T07:00:39.820 回答
3

昨天我遇到了同样的问题,最后我创建了一个更简单的解决方案。

我的要求是在两个不同的数据库中有 2 个不同的表。一张桌子供管理员使用,另一张桌子供普通用户使用。此外,每个表都有自己的散列方式。我最终得到了以下内容(代码也可作为 Github 上的要点:https ://gist.github.com/Xethron/6790029 )

创建一个新的用户提供者。我叫我的 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 使用我的用户提供程序而不是 EloquentUserProviderapp/config/auth.php

'driver' => 'multi',

现在,当我进行身份验证时,我会这样做:

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

然后该类将使用带有 joomlaHasher 的 joomlaUser 模型,并且没有用于散列器的选项...如果使用“另一个”提供程序,它将包括散列器的选项。

这个类是为我的需要而构建的,但可以很容易地改变以适应你的需要。

PS:确保自动加载器可以找到MultiUserProvider,否则它将无法工作。

于 2013-10-02T14:50:39.867 回答
1

我正在使用 Laravel 5 本机身份验证来处理多个用户表...

这并不难,请检查这个要点:

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

更新:对于 Laravel 5,如果您需要更强大的解决方案,请尝试此包:

https://github.com/sboo/multiauth

丹尼尔

于 2015-03-19T13:40:50.013 回答