使用Guard的Laravel Passport多重身份验证

时间:2018-10-17 09:11:00

标签: laravel laravel-5 laravel-5.6 laravel-passport laravel-5.7

我们可以使用具有不同防护措施的laravel护照来为两种不同类型的用户认证API吗? 例如,我们为驱动程序用户提供了驱动程序应用程序,为供应商用户提供了供应商应用程序。两者都有不同的模型驱动程序和供应商。 我们如何使用Laravel Passport使用不同的防护措施来验证两种类型的用户?

4 个答案:

答案 0 :(得分:2)

我设法通过使用一个简单的Middlware创建了多个身份验证(使用laravel / passport)。

步骤1:config / auth.php

将您的用户类别添加到提供商

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

    'api' => [
        'driver' => 'passport',
        'provider' => 'basic_users', // default
    ],        
],

...

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\User::class,
    ],
    'admin_users' => [
        'driver' => 'eloquent',
        'model' => App\AdminUser::class,
    ],
    'basic_users' => [
        'driver' => 'eloquent',
        'model' => App\BasicUser::class,
    ],
],

通过CLI清理缓存

php artisan config:cache

第2步:创建中间件

php artisan make:middleware AdminUserProvider

在app / Http / Middleware中打开新创建的中间件,并更新如下所示的hand方法

public function handle($request, Closure $next)
{
    config(['auth.guards.api.provider' => 'admin_users']);
    return $next($request);
}

第3步:注册您的中间件

将新创建的中间件添加到$ routeMiddleware

protected $routeMiddleware = [
    ...
    'auth.admin' => \App\Http\Middleware\AdminUserProvider::class,
];

并确保它位于$ middlewarePriority的顶部

protected $middlewarePriority = [
    \App\Http\Middleware\AdminUserProvider::class,
    ...
];

第4步:添加要路由的中间件

Route::group(['middleware' => ['auth.admin','auth:api']], function() {

第5步:LoginControllers(AdminUserController和BasicUserController)

public function login()
{
    $validatedData = request()->validate([
        'email' => 'required',
        'password' => 'required|min:6'
    ]);
    // get user object
    $user = AdminUser::where('email', request()->email)->first();
    // do the passwords match?
    if (!Hash::check(request()->password, $user->password)) {
        // no they don't
        return response()->json(['error' => 'Unauthorized'], 401);
    }
    // log the user in (needed for future requests)
    Auth::login($user);
    // get new token
    $tokenResult = $user->createToken($this->tokenName);
    // return token in json response
    return response()->json(['success' => ['token' => $tokenResult->accessToken]], 200);
}

总结:

登录控制器使用Eloquent模型获取用户对象,然后通过Auth :: login($ user)登录用户

然后,对于将来需要身份验证的请求,新的中间件会将api auth Guard提供程序更改为正确的类。

答案 1 :(得分:1)

这里是auth.php和api.php开头的示例

config / auth.php

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Authentication Defaults
    |--------------------------------------------------------------------------
    */

    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],

    /*
    |--------------------------------------------------------------------------
    | Authentication Guards
    |--------------------------------------------------------------------------
    */

    'guards' => [

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

        'driver-api' => [
            'driver' => 'passport',
            'provider' => 'drivers',
        ],

        'vendor-api' => [
            'driver' => 'passport',
            'provider' => 'vendors',
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | User Providers
    |--------------------------------------------------------------------------
    */

    'providers' => [

        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],

        'drivers' => [
            'driver' => 'eloquent',
            'model' => App\Driver::class,
        ],

        'vendors' => [
            'driver' => 'eloquent',
            'model' => App\Vendor::class,
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Resetting Passwords
    |--------------------------------------------------------------------------
    */

    'passwords' => [

        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
        ],

        'drivers' => [
            'provider' => 'drivers',
            'table' => 'password_resets',
            'expire' => 60,
        ],

        'vendors' => [
            'provider' => 'vendors',
            'table' => 'password_resets',
            'expire' => 60,
        ],
    ],

];

routes / api.php

<?php

use Illuminate\Http\Request;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
*/

Route::group(['namespace' => 'Driver', 'prefix' => 'driver/v1', 'middleware' => 'auth:driver-api'], function() {

    // define your routes here for the "drivers"
});

Route::group(['namespace' => 'Vendor', 'prefix' => 'vendor/v1', 'middleware' => 'auth:vendor-api'], function() {

    // define your routes here for the "vendors"
});

您必须修改以下文件:

文件: vendor \ laravel \ passport \ src \ Bridge \ UserRepository.php

复制/粘贴 getUserEntityByUserCredentials 以将其复制并命名为 getEntityByUserCredentials

然后,在新的重复函数中,找到以下内容:

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

并替换为:

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

文件: vendor \ league \ oauth2-server \ src \ Grant \ PasswordGrant.php

in: validateUser 方法在$ username和$ password之后添加:

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

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

这不是原始行

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

完成此操作后,您将能够将一个额外的键/值对传递给您的访问令牌请求,例如:

grant_type => password,
client_id => someclientid
client_secret => somesecret,
username => someuser,
password => somepass,
client_scope => *,
provider => driver-api // Or vendor-api

我希望这对您有帮助

答案 2 :(得分:0)

花了很多时间后,我发现在 Laravel 7 中,除了一些配置之外,不需要自定义代码。有关详细信息,请检查我已经在我的项目中测试并实现的答案 Multi Auth with Laravel 5.4 and Passport

答案 3 :(得分:0)

您不一定需要为每个请求更改配置。 每个警卫都需要一个客户。通过运行创建客户端后

passport:install

确保在数据库中指定了提供程序字段。该值应与auth.providers配置相同。

创建客户端和防护后,在创建访问令牌时使用以下代码。

App::clearResolvedInstance(ClientRepository::class);
app()->singleton(ClientRepository::class, function () {
    return new ClientRepository(User::CLIENT_ID, null); // Client id of the model
});

确保您在oauth_clients表中指定了提供程序。