多用户模型 Laravel JWT Auth

7

我需要在我的Eloquent中使用两个模型:

  • User(用户)
  • OfficeUser(办公室用户)

OfficeUser是在JWT配置中定义的标准模型。现在,我编写了一个中间件来验证每个用户。

authUser:

public function handle($request, Closure $next)
{
    Config::set('auth.providers.users.model', \App\User::class);
    try {

        if (! $user = JWTAuth::parseToken()->authenticate()) {
            return response()->json(['user_not_found'], 404);
        }

    } catch (Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {

        return response()->json(['token_expired'], $e->getStatusCode());

    } catch (Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {

        return response()->json(['token_invalid'], $e->getStatusCode());

    } catch (Tymon\JWTAuth\Exceptions\JWTException $e) {

        return response()->json(['token_absent'], $e->getStatusCode());

    }

    return $next($request);
}

authOfficeUser

public function handle($request, Closure $next)
{
    try {

        if (! $user = JWTAuth::parseToken()->authenticate()) {
            return response()->json(['user_not_found'], 404);
        }

    } catch (Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {

        return response()->json(['token_expired'], $e->getStatusCode());

    } catch (Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {

        return response()->json(['token_invalid'], $e->getStatusCode());

    } catch (Tymon\JWTAuth\Exceptions\JWTException $e) {

        return response()->json(['token_absent'], $e->getStatusCode());

    }

    return $next($request);
}

此外,我还为每个用户提供了登录功能:

LoginUser(登录用户)

if ($user){
        if (Hash::check($request->password, $user->password)) {
            // grab credentials from the request
            $credentials = $request->only('email', 'password');

            try {
                // attempt to verify the credentials and create a token for the user
                Config::set('auth.providers.users.model', \App\User::class);
                if (! $token = JWTAuth::attempt($credentials)) {
                    return response()->json(['error' => 'invalid_credentials'], 401);
                }
            } catch (JWTException $e) {
                // something went wrong whilst attempting to encode the token
                return response()->json(['error' => 'could_not_create_token'], 500);
            }

登录Office用户

if ($user){
        if (Hash::check($request->password, $user->password)) {
            // grab credentials from the request
            $credentials = $request->only('email', 'password');

            try {
                // attempt to verify the credentials and create a token for the user
                Config::set('auth.providers.users.model', \App\OfficeUser::class);
                if (! $token = JWTAuth::attempt($credentials)) {
                    return response()->json(['error' => 'invalid_credentials'], 401);
                }
            } catch (JWTException $e) {
                // something went wrong whilst attempting to encode the token
                return response()->json(['error' => 'could_not_create_token'], 500);
            }

很不幸,当我登录并尝试调用authUser中间件后面的路由时,会出现"user_not_found"的错误。

有人知道为什么会发生这种情况吗?OfficeUser的身份验证正常运作。

2个回答

5

针对任何发现此问题的人发布

虽然不建议有两个用户表,但我曾经遇到了一个类似的要求,需要为我们的客户之一设置JWT。这是我解决这个问题的方式。

无需对`config/auth.php`中的提供程序进行任何更改。

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

]

在您的认证控制器中,通过设置以下内容动态修改提供程序使用的模型: \Config::set('auth.providers.users.model', \App\Trainer::class); 示例代码:
在authenticate()方法中:
if ($credentials['user_type'] == 'consultant') {

\Config::set('auth.providers.users.model', \App\Trainer::class);

} else {
    \Config::set('auth.providers.users.model', \App\User::class);
}

//Find the user

//Create the token
if ($user) {
   $customClaims = ['user_type' => $credentials['user_type']];
   $token = JWTAuth::fromUser($user,$customClaims);
} else {
  return response()->json(['error' => 'invalid_credentials'], 401);
}

你需要在解析token以进行用户身份验证时执行相同的步骤。示例代码:

在getAuthenticatedUser()方法中:


请注意保留HTML标记。我已经为您翻译了上述内容,如果您有其他翻译需求,请告诉我。
$payload = JWTAuth::parseToken()->getPayload();
$user_type = $payload->get('user_type');

if($user_type === 'consultant'){
   \Config::set('auth.providers.users.model', \App\Trainer::class);
}else{
   \Config::set('auth.providers.users.model', \App\User::class);
}

if (!$user = JWTAuth::parseToken()->authenticate()) {
    return response()->json(['user_not_found'], 404);
}

你应该在控制器构造函数中重写配置更改。 - Thiago Pereira
我已经按照你的建议做了所有的事情,但是JWTAuth :: parseToken() - > authenticate()仍然引用User模型而不是给定的模型@amal Ajith。 - Bhargav Variya

0

您可以更改每个控制器中的__construct函数,如下所示。这样jwt就知道要验证哪个模型。

OfficeUserController

function __construct()
{
    Config::set('jwt.user', OfficeUser::class);
    Config::set('auth.providers', ['users' => [
            'driver' => 'eloquent',
            'model' => OfficeUser::class,
        ]]);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接