【问题标题】:Laravel Passport Multiple Authentication using Guards使用 Guards 的 Laravel Passport 多重身份验证
【发布时间】:2019-03-21 21:59:29
【问题描述】:

我们可以使用具有不同保护的 laravel 护照来为两种不同类型的用户验证 API。 例如,我们有驱动程序用户的驱动程序应用程序和供应商用户的供应商应用程序。两者都有不同的模型驱动程序和供应商。 我们如何使用不同的守卫来使用 Laravel Passport 对两种类型的用户进行身份验证?

【问题讨论】:

  • 是的,我认为您可以使用 Laravel Passport 进行多重身份验证,它不是内置功能,但您可以自己编写代码。

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


【解决方案1】:

我设法通过使用一个简单的中间件创建了多个身份验证(使用 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 步:登录控制器(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 provider 更改为正确的类。

【讨论】:

  • 如果我想查看管理员的个人资料,我们如何处理下一个请求,我们如何在下一个请求中获取用户的个人资料?
  • 您可以使用令牌通过模型来确定用户是谁,但我不认为访问令牌是标识符。他们确定您是否可以访问某些内容。您更有可能将此代码用作您的身份验证层,然后使用生成的令牌来访问另一个服务。您可以传入任何您想要的信息,即 POST 数据。
  • @rharvey 谢谢你的解决方案,但我收到类似错误:BadMethodCallException: Call to undefined method App\Merchant::getAuthIdentifierName() in file /home/dimonky/api.example.com/ vendor/laravel/framework/src/Illuminate/Support/Traits/ForwardsCalls.php 第 50 行
  • 嗨@mdkamrul,很抱歉,我已经很久没有看 Laravel 了,所以我可能很难提供帮助。但是,该错误表明您有一个名为 Merchant 的类,它正在寻找一个不存在的名为 getAuthIdentifierName 的方法。我假设这是自定义代码?您可能需要检查配置并确保已定义所有相关类
【解决方案2】:

编辑:Passport 现在支持多个保护用户提供程序。更多信息请参考以下链接:

Multiple Authentication Guards

Support For Multiple Guards


老答案(不推荐)

这里是 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

希望对你有帮助

【讨论】:

  • 非常感谢您提供此解决方案。但我无法理解最后一部分 grant_type => password, client_id => someclientid client_secret => somesecret, username => someuser, password => somepass, client_scope => *, provider => driver-api // 或 vendor-api
  • 我们如何检索已登录的驱动程序或供应商的令牌?
  • @AhmarArshad 这是您“请求令牌”的地方,请参阅文档laravel.com/docs/5.6/passport#password-grant-tokens
  • 改为更改“vendor”文件夹,而不是任何解决方案
  • @Harat 您如何看待拥有另一个 customPassport 文件夹并创建所需文件并扩展原始文件。然后在你的composer.json中,dont-discover部分添加“laravel/passport”,然后在你的app.php中注册你自己的CustomPassportServiceProvider
【解决方案3】:

经过一段时间我发现在 Laravel 7 中除了一些配置之外不需要自定义代码。有关详细信息,请查看我在我的项目中测试和实施的这个答案 Multi Auth with Laravel 5.4 and Passport

【讨论】:

    【解决方案4】:

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

    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 表中指定了提供者。

    【讨论】:

      猜你喜欢
      • 2021-06-25
      • 2020-12-30
      • 1970-01-01
      • 2017-07-08
      • 2017-05-13
      • 1970-01-01
      • 2019-01-31
      • 2019-12-14
      • 1970-01-01
      相关资源
      最近更新 更多