2017-02-19 7 views
3

Laravel Passport를 사용하여 다중 인증을 설정하려고하지만 지원하지 않습니다. 액세스 토큰을 원하는 사용자의 사용자 이름/암호를 전달해야하는 토큰을 발행하려면 암호 부여를 사용하고 있습니다.Laravel 5.4 및 Passport가있는 다중 인증

나는 3 개의 경비원/제공자 설정을 총 4 개 가지고 있습니다. 사용자, 공급 업체, 관리자 및 API

2 인증을 받으려면 각 사용자가 토큰을 발급 받아야합니다. 그러나 Passport는 자동으로 API 인증 공급자를 사용하지만 어떤 사용자가 로그인했는지에 따라 변경해야합니다. 사용자가 사용자 제공자 인 경우 및 해당 공급 업체의 경우 공급 업체입니다.

Passport는 현재 사용자 유형이 1 개만 지원되므로 기본값은 API 제공자입니다.

더 좋은 방법이 있습니까? 대신 역할 기반 인증을 사용해야합니까?

답변

3

여전히 필요한 경우. 내가 역할과 갈 선호

는, 그에 대한 놀라운 플러그인이 : https://github.com/larapacks/authorization

하지만 당신은 어떻게 든 것을 필요로하는 경우, 당신은 단계 노호 다음 사용할 수 있습니다.

멀티 가드의 경우 일부 코드를 덮어 써야합니다.

PassportServiceProvider를로드하는 대신 자신을 만들고 PassportServiceProvider를 확장하고 makePasswordGrant 메서드를 덮어 씁니다. 이 방법에서는 자신의 저장소 확장을 위해 Passport UserRepository를 변경합니다. 사용자 저장소에서 동적 속성에 대한 정적 모델 구성을 변경해야합니다 (요청 속성에서로드하지만 어디에서나 얻을 수 있습니다).

다른 것을 덮어 써야 할 수도 있지만 시험을 치고 작동합니다.

예 :

PassportServiceProvider

namespace App\Providers; 

use League\OAuth2\Server\AuthorizationServer; 
use League\OAuth2\Server\Grant\PasswordGrant; 
use Laravel\Passport\PassportServiceProvider as BasePassportServiceProvider; 
use Laravel\Passport\Passport; 

class PassportServiceProvider extends BasePassportServiceProvider 
{ 
    /** 
    * Create and configure a Password grant instance. 
    * 
    * @return PasswordGrant 
    */ 
    protected function makePasswordGrant() 
    { 
     $grant = new PasswordGrant(
      $this->app->make(\App\Repositories\PassportUserRepository::class), 
      $this->app->make(\Laravel\Passport\Bridge\RefreshTokenRepository::class) 
     ); 

     $grant->setRefreshTokenTTL(Passport::refreshTokensExpireIn()); 

     return $grant; 
    } 

} 

UserRepository

namespace App\Repositories; 

use App; 
use Illuminate\Http\Request; 
use League\OAuth2\Server\Entities\ClientEntityInterface; 
use Laravel\Passport\Bridge\UserRepository; 
use Laravel\Passport\Bridge\User; 
use RuntimeException; 

class PassportUserRepository extends UserRepository 
{ 
    /** 
    * {@inheritdoc} 
    */ 
    public function getUserEntityByUserCredentials($username, $password, $grantType, ClientEntityInterface $clientEntity) 
    { 
     $guard = App::make(Request::class)->attributes->get('guard') ?: 'api'; 
     $provider = config("auth.guards.{$guard}.provider"); 


     if (is_null($model = config("auth.providers.{$provider}.model"))) { 
      throw new RuntimeException('Unable to determine user model from configuration.'); 
     } 


     if (method_exists($model, 'findForPassport')) { 
      $user = (new $model)->findForPassport($username); 
     } else { 
      $user = (new $model)->where('email', $username)->first(); 
     } 


     if (! $user) { 
      return; 
     } elseif (method_exists($user, 'validateForPassportPasswordGrant')) { 
      if (! $user->validateForPassportPasswordGrant($password)) { 
       return; 
      } 
     } elseif (! $this->hasher->check($password, $user->password)) { 
      return; 
     } 

     return new User($user->getAuthIdentifier()); 
    } 
} 

PS : 죄송합니다 나의 나쁜 영어.

2

기본 라이브러리 파일을 수정해야합니다.

1) 파일 : 벤더 \ laravel의 \ 여권 \ SRC \ 브리지 \ UserRepository.php

getUserEntityByUserCredentials을 찾아 완벽한 방법을 복사하고 이름 getEntityByUserCredentials와 아래에이 방법을 붙여 넣습니다. 어딘가에서 사용되기 때문에 main 함수를 수정하지 마십시오.

$provider = config('auth.guards.api.provider'); 

과로 교체 :

//Add the $provider variable at last or replace this line. 
public function getEntityByUserCredentials($username, $password, $grantType, ClientEntityInterface $clientEntity, $provider) 

그런 다음 새 복제 기능으로, 아래 찾을

$provider = config('auth.guards.'.$provider.'.provider'); 

2) 파일 : 공급 업체 \ 리그 \의 OAuth2를 서버 \ src \ Grant \ PasswordGrant.php

validateUser 다음 코드를 행 번호 뒤에 추가하십시오. 88

$provider = $this->getRequestParameter('provider', $request); 

if (is_null($provider)) { 
    throw OAuthServerException::invalidRequest('provider'); 
} 

$user = $this->userRepository->getEntityByUserCredentials(
     $username, 
     $password, 
     $this->getIdentifier(), 
     $client, 
     $provider 
    ); 

에 다음 코드를 대신 추가 한 후 지금 우체부 사용

provider = api_vendors 
OR 
provider = api_admins 
OR 
provider = api_users 
And so on.... 

메이크업처럼 입력 필드에 제공 필드를 추가 이것을 시도 공급자를 추가하고 드라이버를 설정했는지 확인하십시오. config/auth.php에서

'guards' => [ 
'api_admins' => [ 
    'driver' => 'passport', 
    'provider' => 'admins', 
    ], 
    'api_vendors' => [ 
    'driver' => 'passport', 
    'provider' => 'vendors', 
    ], 

나는 이것이 도움이되기를 바랍니다.

0

Laravel 패스포트는 사용자로만 제공 업체로 작동합니다. PasswordGrant & UserRepository를 사용하여 위의 변경 사항을 추가하여 토큰을 가져 오더라도 Post 및 get 요청 API 호출은 사용자가 아닌 변경된 여권 공급자와 작동하지 않습니다.

공급 업체 및 고객으로 필요한 경우 세션 드라이버로 다중 인증을 만드는 것이 좋습니다. 등 전용 테이블 컬럼 관리, API, 공급 업체를 지원하는 여권 '사용자'모델, 나는이 문제에 대한 작은 패키지를 만든 laravel-multiAuth

0

여기

환매 약정을 할 수 있습니다. 전체 문서 링크는 다음과 같습니다 link

그러나 user 엔티티가 로그인하면 항상 가드와 제공자를 확인합니다.

'guards' => [ 
    'web' => [ 
     'driver' => 'session', 
     'provider' => 'users', 
    ], 

    'api' => [ 
     'driver' => 'passport', 
     'provider' => 'users', 
    ], 

    'customers' => [ 
     'driver' => 'passport', 
     'provider' => 'customers' 
    ], 
], 

'providers' => [ 
    'users' => [ 
     'driver' => 'eloquent', 
     'model' => 'App\User', 
    ], 
    /** 
    * This is the important part. You can create as many providers as you like but right now, 
    * we just need the customer 
    */ 
    'customers' => [ 
     'driver' => 'eloquent', 
     'model' => 'App\Customer', 
    ], 
], 

당신은이 같은 컨트롤러가 있어야합니다

<?php 

namespace App\Http\Controllers\Auth; 

use App\Customers\Customer; 
use App\Customers\Exceptions\CustomerNotFoundException; 
use Illuminate\Database\ModelNotFoundException; 
use Laravel\Passport\Http\Controllers\AccessTokenController; 
use Laravel\Passport\TokenRepository; 
use League\OAuth2\Server\AuthorizationServer; 
use Psr\Http\Message\ServerRequestInterface; 
use Lcobucci\JWT\Parser as JwtParser; 

class CustomerTokenAuthController extends AccessTokenController 
{ 
    /** 
     * The authorization server. 
     * 
     * @var \League\OAuth2\Server\AuthorizationServer 
     */ 
    protected $server; 

    /** 
     * The token repository instance. 
     * 
     * @var \Laravel\Passport\TokenRepository 
     */ 
    protected $tokens; 

    /** 
     * The JWT parser instance. 
     * 
     * @var \Lcobucci\JWT\Parser 
     */ 
    protected $jwt; 

    /** 
     * Create a new controller instance. 
     * 
     * @param \League\OAuth2\Server\AuthorizationServer $server 
     * @param \Laravel\Passport\TokenRepository $tokens 
     * @param \Lcobucci\JWT\Parser $jwt 
     */ 
    public function __construct(AuthorizationServer $server, 
           TokenRepository $tokens, 
           JwtParser $jwt) 
    { 
     parent::__construct($server, $tokens, $jwt); 
    } 

    /** 
     * Override the default Laravel Passport token generation 
     * 
     * @param ServerRequestInterface $request 
     * @return array 
     * @throws UserNotFoundException 
     */ 
    public function issueToken(ServerRequestInterface $request) 
    { 
     $body = (parent::issueToken($request))->getBody()->__toString(); 
     $token = json_decode($body, true); 

     if (array_key_exists('error', $token)) { 
      return response()->json([ 
       'error' => $token['error'], 
       'status_code' => 401 
      ], 401); 
     } 

     $data = $request->getParsedBody(); 

     $email = $data['username']; 

     switch ($data['provider']) { 
      case 'customers'; 

       try { 

       $user = Customer::where('email', $email)->firstOrFail(); 

       } catch (ModelNotFoundException $e) { 
        return response()->json([ 
         'error' => $e->getMessage(), 
         'status_code' => 401 
        ], 401); 
       } 

       break; 

      default : 

       try { 

       $user = User::where('email', $email)->firstOrFail(); 

       } catch (ModelNotFoundException $e) { 
        return response()->json([ 
         'error' => $e->getMessage(), 
         'status_code' => 401 
        ], 401); 
       }   
     } 

     return compact('token', 'user'); 
    } 
} 

및 요청이 있어야한다 :

POST /api/oauth/token HTTP/1.1 
Host: localhost 
Content-Type: application/x-www-form-urlencoded 
Cache-Control: no-cache 

grant_type=password&username=test%40email.com&password=secret&provider=customers 

는 사용자에 기록됩니다 컨트롤러에서 확인하려면, 당신은 할 수있다 :

auth()->guard('customers')->user()