如何使用相同的身份验证保护验证多种类型的用户 [Lumen]

Posted

技术标签:

【中文标题】如何使用相同的身份验证保护验证多种类型的用户 [Lumen]【英文标题】:How to authenticate multiple type of user with same auth guard [Lumen] 【发布时间】:2021-02-22 15:58:48 【问题描述】:

我正在使用 Lumen 8 开发 API 应用程序。我有 3 种类型的用户。对于他们,我使用 3 种不同的模型。我正在使用 JWT 身份验证 [packege-tymon/jwt-auth]。

这是我的 Auth.php 配置。我使用 3 种类型的身份验证保护

return [
'defaults' => [
    'guard' => env('AUTH_GUARD', 'user'),
    'passwords' => 'users',
],

'guards' => [
    'user' => [
        'driver' => 'jwt',
        'provider' => 'users',
    ],
    'vendor_user' => [
        'driver' => 'jwt',
        'provider' => 'vendor_users',
    ],
    'super_user' => [
        'driver' => 'jwt',
        'provider' => 'super_users',
    ],
],

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => \App\Models\User::class
    ],
    'vendor_users' => [
        'driver' => 'eloquent',
        'model' => \App\Models\VendorUser::class
    ],
    'super_users' => [
        'driver' => 'eloquent',
        'model' => \App\Models\SuperUser::class
    ]
],
'passwords' => [
    'users' => [
        'provider' => 'users',
        'table' => 'password_resets',
        'expire' => 60,
        'throttle' => 60,
    ],
    'vendor_users' => [
        'provider' => 'vendor_users',
        'table' => 'password_resets',
        'expire' => 60,
        'throttle' => 60,
    ],
    'super_users' => [
        'provider' => 'super_users',
        'table' => 'password_resets',
        'expire' => 60,
        'throttle' => 60,
    ],
],
'password_timeout' => 10800,

];

对于登录,我使用提到的 auth guard 使用 3 条不同的路由。

    protected function login(Request $request, $guard = 'user')

    //validate incoming request
    $this->validate($request, [
        'email' => 'required|string',
        'password' => 'required|string',
    ]);

    $credentials = $request->only(['email', 'password']);

    if (! $token = Auth::guard($guard)->attempt($credentials)) 
        return response()->json(responseFormat(ERROR,___('Unauthorized')), 401);
    

    return $this->respondWithToken($token);


public function userLogin(Request $request)

    return $this->login($request,'user');


public function superUsersLogin(Request $request)

    return $this->login($request,'super_user');


public function vendorUsersLogin(Request $request)

    return $this->login($request,'vendor_user');

我已经设法从所有 3 种类型的用户那里获得了成功登录的令牌。

但是当我使用 Authenticate 中间件对所有用户进行身份验证时遇到问题

public function handle($request, Closure $next, $guard = null)

    if ($this->auth->guard($guard)->guest()) 
        return response(responseFormat(ERROR,'Unauthorized.'), 401);
    

    return $next($request);

它仅适用于默认的 auth-guard 类型用户(即用户保护)。如果我想对其他用户类型进行身份验证,我必须使用不同的路由并说明要使用的 auth-guard。

$router->group(['middleware' => 'auth','prefix' => 'api'], function ($router)

    $router->get('/send-email', 'EmailController@sendEmail');
    $router->get('/users', 'UsersController@users');


);
$router->group(['middleware' => 'auth:vendor_user','prefix' => 'api/vendor'], function ($router)

    $router->get('/send-email', 'EmailController@sendEmail');
    $router->get('/users', 'UsersController@users');

);
$router->group(['middleware' => 'auth:super_user','prefix' => 'api/super_user'], function ($router)

    $router->get('/send-email', 'EmailController@sendEmail');
    $router->get('/users', 'UsersController@users');

);

有什么方法可以对同一路由的所有 3 种类型的用户进行身份验证?这样我就不必为每种类型的用户选择不同的路线了。

$router->group(['middleware' => 'auth','prefix' => 'api'], function ($router)

    $router->get('/send-email', 'EmailController@sendEmail');
    $router->get('/users', 'UsersController@users');
);

就像这个 API 可以被所有 3 种类型的用户使用,并通过相同的 auth-guard 或其他方式进行身份验证。

BS:我必须为 3 种类型的用户使用 3 张不同的表。

【问题讨论】:

【参考方案1】:

创建一个单独的中间件来尝试凭证。然后,设置应该使用的默认保护 Auth。您无需通过守卫即可登录。

在登录控制器中

    public function  __construct()
    
        $this->middleware('SetAuthGuard:user')->except('logout');
        $this->middleware('SetAuthGuard:vendor_users')->except('logout');
        $this->middleware('SetAuthGuard:super_users')->except('logout');
    

SetAuthGuard 中间件



    public function handle(Request $request, Closure $next, ...$guards)
    
        $guards = empty($guards) ? [null] : $guards;
        $credentials = $request->only('email','password');
        foreach ($guards as $guard) 
            if (Auth::guard($guard)->attempt($credentials)) 
                Auth::shouldUse($guard);
            
        
        return $next($request);
    

【讨论】:

以上是关于如何使用相同的身份验证保护验证多种类型的用户 [Lumen]的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 OAuth2 身份验证保护私有数据?

Vue.js:如何保护登录组件免受经过身份验证的用户的影响

如何在不经过注册用户身份验证的情况下保护公共API请求

如何在 Jenkins 中设置多种身份验证方式,例如 LDAP 和 Jenkins 用户数据库?

Asp.Net Web API JWT 身份验证

如何通过查询身份验证保护 REST API