【问题标题】:Laravel Passport - Multiple guards issueLaravel Passport - 多个警卫问题
【发布时间】:2020-11-23 08:20:24
【问题描述】:

提前谢谢你, 我想要多个 laravel 护照保护,因为我的系统有 2 种用户类型,1)管理员,2)普通用户。 对于两者,我都有单独的路由和身份验证模块(登录、注册、注销等)。所以我需要一个单独的护照保护来进行 API 身份验证。我添加的一些代码如下

config/auth.php 如下所示

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

        'api' => [
            'driver' => 'passport',
            'provider' => 'users',
            'hash' => false,
        ],
        'api-admin' => [
            'driver' => 'passport',
            'provider' => 'admins',
            'hash' => false,  
        ]
    ],

在这里我为管理员和用户定义了 2 个守卫

'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],
        'admins' => [
            'driver' => 'eloquent',
            'table' => App\Models\Admin::class,
        ],
],

在这里我为管理员和用户定义了 2 个提供者

现在我正在创建类似的令牌

$tokenResult = $user->createToken('TOKEN_DEMO');        
$token = $tokenResult->token;
$token->save();
$accessToken = $tokenResult->accessToken;

对于 user_id = 1 的管理员用户,它的生成效果与预期一样好(例如,考虑 user_id = 1) 这是关于为管理员用户生成令牌

与普通用户登录并生成令牌的方式与上述相同,那么这也会为oauth_clients表中user_id = 1的用户生成令牌

表格看起来像屏幕截图中提到的那样

担心的是,如果普通用户注销,那么管理员用户的令牌将被自动销毁,因为 oauth_clients 表中两者的 user_id 都是 1,而两者的守卫不同

请帮帮我

【问题讨论】:

    标签: php oauth laravel-passport


    【解决方案1】:

    这也是一个安全问题,因为您与管理员具有相同 id 的用户可以通过管理员身份验证中间件。 以下方法是我发现的最干净的解决方法。 你必须为你的警卫使用不同的客户端。 你必须跑

    passport:install
    

    如果您有两个使用 Passport 的警卫,则执行两次。它将生成两个客户端。 在新版本的 Passport(我认为是 Laravel 8 发布之后)中,当您创建客户端时,它会要求您提供提供者(在 auth.providers 配置中定义)。每个提供商都需要一个客户。如果您使用的是旧版本,您可以在 oauth_clients 表中手动分配提供者。 现在生成令牌时,您必须指定客户端 ID。 在旧版本中,您可以通过更改其中一个 Passport 类的公共属性来做到这一点,但现在您应该再次注册 ClientRepository。

    App::clearResolvedInstance(ClientRepository::class);
    app()->singleton(ClientRepository::class, function () {
        return new ClientRepository(User::CLIENT_ID, null); // You should give the client id in the first parameter
    });
    $token = $user->createToken('TOKEN-EXAMPLE');
    $accessToken = $token->accessToken;
    

    现在,如果您检查访问令牌表,您会发现客户端 ID 不同。 现在一切都很好。

    您提到撤销令牌可能存在问题,但我相信即使在您的情况下(使用相同的客户端而不指定提供者),如果您撤销与管理员具有相同 ID 的用户令牌,管理员的令牌仍将保留。撤销用户令牌:

    $user = Auth::guard('user-api')->user();
    $user->token()->revoke();
    

    【讨论】:

    • 你好,非常感谢你的回答,你节省了我的时间,我已经实现了你的代码来创建令牌,同时关于撤销令牌,我有一个问题,目前,我正在撤销所有现有的特定用户登录时的令牌,因此该用户的所有先前会话都将被销毁,我这样做是通过循环遍历用户的令牌然后 $token->delete() 但它也在删除管理员客户端令牌,我只想删除用户客户端令牌
    • @RonakSolanki 你好,不客气。您不应该删除某个用户的所有令牌。正如我在回答末尾提到的,您应该只撤销当前用户的令牌。 $user = Auth::guard('user-api')->user(); $user ->token()->revoke();无论如何,删除令牌不是一个好习惯。即使你想禁用一个令牌,使用撤销函数 $token->revoke()
    • 是的,我知道,如果我想撤销特定客户的特定用户之前的所有令牌,那么有可能吗?目前,如果我撤销用户角色的令牌,那么它也会撤销管理员
    • @RonakSolanki 是的。首先获取该客户端的令牌。 $tokens = \Laravel\Passport\Token::where('client_id', 1)->get();然后使用 Foreach 并在每个令牌上调用 revoke
    • 好的,非常感谢您的帮助和时间 :)
    【解决方案2】:

    守卫出现在令牌上的任何地方吗?还是令牌只有范围?如果是这样,当你可以使用范围时,为什么还要使用警卫...... 美好的一天!

    [编辑]

    在我的情况下,我使用角色和权限来编写我的范围...角色和权限是基于警卫的,除非我们添加“管理员”键(就我而言)“护照”驱动器和“用户”提供者...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-02
      • 2021-02-02
      • 2021-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多