authentication - 오라클 - 다른 테이블 컬럼 가져 오기



2 개의 다른 테이블로 인증 (4)

다른 테이블과 사용자와 함께 새로운 "인증"설정을 만들어야합니다. 나는 "admin"사용자를위한 하나의 테이블과 일반 사용자를위한 또 다른 테이블을 가지고있다.

하지만 다른 구성으로 Auth 다른 인스턴스를 만들려면 어떻게해야합니까?


Answer #1

나는 어제 같은 문제가 있었고 훨씬 더 간단한 해결책을 만들었습니다.

내 요구 사항 어디에 두 개의 서로 다른 두 개의 테이블에있는 서로 다른 데이터베이스. 한 테이블은 관리자를위한 테이블이었고 다른 테이블은 일반 사용자를위한 테이블이었습니다. 또한 각 테이블에는 자체 해싱 방법이 있습니다. 나는 다음과 같이 끝냈다. (코드는 Github의 요지로도 이용 가능하다 : https://gist.github.com/Xethron/6790029 )

새 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 에서 EloquentUserProvider 대신 사용자 제공 업체를 사용하라고했습니다.

'driver' => 'multi',

이제, 인증 할 때, 나는 그렇게합니다 :

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

그런 다음 클래스는 joomlaHasher를 사용하여 joomlaUser 모델을 사용하고 hasher에 대한 옵션을 사용하지 않습니다. 'another'공급자를 사용하는 경우 hasher에 대한 옵션이 포함됩니다.

이 클래스는 필자가 요구했지만 쉽게 필요에 맞게 변경할 수 있습니다.

추신 : 오토로더가 MultiUserProvider를 찾을 수 있는지 확인하십시오. 그렇지 않으면 작동하지 않습니다.


Answer #2

새로운 Auth 클래스를 "에뮬레이션"할 수 있습니다.

Laravel Auth 구성 요소는 기본적으로 Illuminate\Auth\Guard 클래스이며이 클래스에는 몇 가지 종속성이 있습니다.

기본적으로 새로운 Guard 클래스와 일부 facades를 만들어야합니다.

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

이 서비스 제공자에서는 '새로운'암호 미리 알림 구성 요소를 만드는 방법에 대한 몇 가지 예를 제시합니다.

이제 인증을위한 것과 비밀번호 미리 알림을위한 두 개의 새로운 facades를 만들어야합니다.

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

물론 암호 미리 알림의 경우 작업하기 위해 데이터베이스에 테이블을 만들어야합니다. 이 예에서 서비스 공급자의 registerReminderDatabaseRepository 메소드에서 볼 수있는 것처럼 테이블 이름은 client_reminders 여야합니다. 테이블 구조는 원래 미리 알림 테이블과 동일합니다.

그런 다음 Auth 클래스와 동일한 방법으로 ClientAuth 사용할 수 있습니다. Password 클래스가있는 ClientPassword 에서도 마찬가지입니다.

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에서는 방금 다중 인증을 도입 했으므로이 버전에서는 더 이상 필요하지 않습니다.


Answer #3

이 문제를 직접 해결하려고 시도하면서 훨씬 간단한 방법을 발견했습니다. 기본적으로 Auth에 대한 팩토리 클래스로 사용되는 기본 Auth 하나를 대체 할 사용자 정의 ServiceProvider를 작성했으며 여러 로그인 유형에 대해 여러 인스턴스를 가질 수 있습니다. 나는 또한 여기에 찾을 수있는 패키지에 모두 붙어 : 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::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();

또한 여러 개의 사용자 유형으로 동시에 로그인 할 수 있으므로 작업중인 프로젝트에 대한 요구 사항이었습니다. 그것이 내가 아닌 다른 누군가에게 도움이되기를 바랍니다.

업데이트 - 2014 년 2 월 27 일

이 답변에서 방금 오는 사람들을 위해 방금 전에 동일한 미리보기 스타일 방식으로 액세스 할 수있는 미리 알림에 대한 지원을 추가했습니다.


Answer #4

좋아, 나는 똑같은 문제가 있었는데 여기 어떻게 해결 했는가?

실제로 laravel 4에서는 런타임시 auth configs를 간단히 변경할 수 있으므로 트릭을 수행하기 위해 단순히 App :: before 필터에서 다음을 수행 할 수 있습니다.

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

이렇게하면 관리자 URL에있을 때 Auth 구성 요소가 관리자 모델을 사용하게됩니다. 그러나 이전에 로그인 한 경우 admin 사이트에 로그인 할 수있는 동일한 ID를 가진 admin 및 users 테이블에 두 명의 사용자가있는 경우 로그인 세션 키가 동일하기 때문에 새로운 문제가 발생할 수 있습니다. 일반 사용자! 두 가지 다른 authetications를 완전히 독립적으로 만들기 위해서 저는이 트릭을했습니다 :

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 클래스의 일부 메소드를 다시 작성하여 admin 사이트에 대해 다른 세션 키를 생성한다는 것을 알 수 있습니다. 그런 다음 관리자 사이트의 드라이버를 변경했습니다. 행운을 빕니다.





laravel-4