Laravel 护照 - 多重警卫问题

Laravel Passport - Multiple guards issue

提前谢谢你, 我需要多个 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) 这是关于为管理员用户生成令牌

普通用户登录和生成令牌的方式与上面相同,那么这也会为 user_id = 1 in oauth_clients table[= 的用户生成令牌18=]

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

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

请帮我解决同样的问题

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

passport:install

如果你有两个守卫使用 Passport,则两次。它将生成两个客户端。 在新版本的 Passport 中(我认为在 Laravel 8 发布之后)当你创建一个客户端时它会要求你提供一个提供者(在 auth.providers 配置中定义)。每个供应商都需要一个客户。如果您使用的是旧版本,您可以在 oauth_clients table 中手动分配供应商。 现在生成令牌时,您必须指定客户端 ID。 在旧版本中,您可以通过更改 Passport 类 之一的 public 属性 来完成此操作,但现在您应该再次注册 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;

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

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

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

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

[编辑]

在我的例子中,我使用角色和权限来编写我的范围...角色和权限是基于守卫的,除非我们添加 'admin' 密钥与(在我的情况下)'passport' 驱动器和 'user' 提供商...