【问题标题】:Lravel 5.4: JWT API with multi-auth on two tables one works the other notLaravel 5.4:在两个表上具有多重身份验证的 JWT API 一个有效,另一个无效
【发布时间】:2018-08-19 02:34:06
【问题描述】:

我正在使用...

  • Laravel 5.4
  • tymon/jwt-auth : 1.0.0-rc.2

我的应用程序有两个身份验证 API,一个是 customers,另一个是 drivers,每个都有自己的表。

现在让我简要介绍一下JWT 软件包的安装以及我对它所做的更新。

  • 我完全按照JWT 文档中的说明安装了该软件包。
  • 现在来到quick start,这里我更新了两个Models,一个是User,第二个是Driver
  • 再次来到Configure Auth guard这里我使用了两个guards的配置让我展示一下我的auth.php的快照。

    'defaults' => [
        'guard'     => 'api',
        'passwords' => 'users',
    ], 
    
    'guards' => [
            'web' => [
                'driver'   => 'session',
                'provider' => 'users',
            ],
    
            'api' => [
                'driver'   => 'jwt',
                'provider' => 'users',
            ],
    
            'driver'    => [
                'driver'   => 'session',
                'provider' => 'drivers',
            ],
    
            'driver-api' => [
                'driver'   => 'jwt',
                'provider' => 'drivers',
            ],
        ],
    
    'providers' => [
            'users'     => [
                'driver' => 'eloquent',
                'model'  => App\Models\User::class,
            ],
    
            'drivers'   => [
                'driver' => 'eloquent',
                'model'  => App\Models\Driver::class,
            ],
        ],
    
  • 现在继续使用authentication routes 申请,这是我的Routes 两个Models

这是UserDriver 路由

Route::group( [
    'prefix'     => 'auth',
    'middleware' => 'api'
], function () {
    .......
});

Route::group( [
    'prefix'     => 'driver',
    'middleware' => 'api'
], function () {
   .......
});
  • 现在是AuthController

JWT 文档中,construct 是这样写的。

public function __construct()
    {
        $this->middleware('auth:api', ['except' => ['login']]);
    }

我发现一些文章建议在我们拥有的两种模型之间切换。

所以现在我的控制器看起来像现在这样。

public function __construct() {
        $this->user   = new User;
        $this->driver = new Driver;
    }

public function userLogin( Request $request ) {
        Config::set( 'jwt.user', 'App\Models\User' );
        Config::set( 'auth.providers.users.model', User::class );
        $credentials = $request->only( 'email', 'password' );
        $token       = null;
        try {
            if ( $token = $this->guard()->attempt( $credentials ) ) {
                return response()->json( [
                    'response' => 'error',
                    'message'  => 'invalid_email_or_password',
                ] );
            }
        } catch ( JWTAuthException $e ) {
            return response()->json( [
                'response' => 'error',
                'message'  => 'failed_to_create_token',
            ] );
        }

        return response()->json( [
            'response' => 'success',
            'result'   => [
                'token'   => $token,
                'message' => 'I am front user',
            ],
        ] );
    }

    public function driverLogin( Request $request ) {
        Config::set( 'jwt.user', 'App\Models\Driver' );
        Config::set( 'auth.providers.users.model', Driver::class );
        $credentials = $request->only( 'email', 'password' );
        $token       = null;
        try {
            if ( ! $token = $this->guard()->attempt( $credentials ) ) {
                return response()->json( [
                    'response' => 'error',
                    'message'  => 'invalid_email_or_password',
                ] );
            }
        } catch ( JWTAuthException $e ) {
            return response()->json( [
                'response' => 'error',
                'message'  => 'failed_to_create_token',
            ] );
        }

        return response()->json( [
            'response' => 'success',
            'result'   => [
                'token'   => $token,
                'message' => 'I am driver user',
            ],
        ] );
    }

public function me() {
        return response()->json( $this->guard()->user() );
    }

public function logout() {
        $this->guard()->logout();

        return response()->json( [ 'message' => 'Successfully logged out' ] );
    }

public function refresh() {
        return $this->respondWithToken( $this->guard()->refresh() );
    }

protected function respondWithToken( $token ) {
        return response()->json( [
            'access_token' => $token,
            'token_type'   => 'bearer',
            'expires_in'   => $this->guard()->factory()->getTTL() * 60
        ] );
    }

public function guard() {
        return Auth::guard();
    }  

现在正在发生以及我面临的问题

现在驱动程序 api 仅作为 login 工作。

localhost:8000/api/driver/login 工作正常

但是当尝试像这样获取驱动程序用户id

localhost:8000/api/driver/me它返回空array

第二期来了。

使用来自interface 的登录名,例如。 http://localhost:8000/login 它返回登录屏幕没有任何错误,因为登录信息是正确的,但是 auth.php 中的 defaults'guard'=>'api' 如果我将其更改为 'guard'=>'web' 它会正确登录。

即使是 User API 对于 Ex。 localhost:8000/api/auth/login 总是返回

{
    "response": "error",
    "message": "invalid_email_or_password"
}

更新

我解决了一半 我将AuthController 更新为类似这样。

public function __construct() {
        if ( Request()->url() == '/api/driver/me' ) {
            $this->middleware( 'auth:driver-api', [ 'except' => [ 'login' ] ] );
        } elseif ( Request()->url() == '/api/customer/me' ) {
            $this->middleware( 'auth:api', [ 'except' => [ 'login' ] ] );
        }
    }

和登录功能是这样的。

public function login() {
        if ( Request()->url() == '/api/driver' ) {
            Config::set( 'auth.providers.users.model', Driver::class );
            $credentials = request( [ 'email', 'password' ] );

            if ( ! $token = auth()->attempt( $credentials ) ) {
                return response()->json( [ 'error' => 'Unauthorized' ], 401 );
            }

            return $this->respondWithToken( $token );
        }

        Config::set( 'auth.providers.users.model', User::class );
        $credentials = request( [ 'email', 'password' ] );

        if ( ! $token = auth()->attempt( $credentials ) ) {
            return response()->json( [ 'error' => 'Unauthorized' ], 401 );
        }

        return $this->respondWithToken( $token );

    }

但是auth.php 还是有问题

'defaults' => [
        'guard'     => 'driver-api',
        'passwords' => 'users',
    ], 

在这里我需要将'guard'=>'api' 切换为'guard'=>'driver-api' 以防URL 请求为localhost:8000/api/driver/login'guard'=>'api' 以防URL 请求为localhost:8000/api/customer/login 以任何方式执行此操作。

更新 2

这里是driver Model

use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Foundation\Auth\User as Authenticatable;

class Driver extends Authenticatable implements JWTSubject {
    protected $guard = 'driver';

    protected $fillable = [
        ...
        'email',
        'password',
        ...
    ];

    protected $hidden = [
        'password',
        'remember_token',
    ];

    public function getJWTIdentifier() {
        return $this->getKey();
    }

    public function getJWTCustomClaims() {
        return [];
    }
}

还有UserModel

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Tymon\JWTAuth\Contracts\JWTSubject;

class User extends Authenticatable implements JWTSubject {
    use Notifiable;

    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    protected $hidden = [
        'password',
        'remember_token',
    ];

    public function getJWTIdentifier() {
            return $this->getKey();
        }

        public function getJWTCustomClaims() {
            return [];
        }

我需要一些帮助,请出主意。

【问题讨论】:

    标签: php laravel authentication jwt laravel-5.4


    【解决方案1】:

    我在 jwt 中使用多重身份验证时的示例

    我有 2 个模型: 1. 用户 2. 管理员

    路线:

    Route::post('auth/userlogin', 'ApiController@userLogin');
    Route::post('auth/adminlogin', 'ApiController@adminLogin');
    

    控制器:

    namespace App\Http\Controllers;
    
    use Illuminate\Http\Request;
    use App\Http\Controllers\Controller;
    use App\Http\Requests;
    use Config;
    use JWTAuth;
    use JWTAuthException;
    use App\User;
    use App\Admin;
    
    class ApiController extends Controller
    {
    
        public function __construct()
        {
            $this->user = new User;
            $this->admin = new Admin;
        }
    
        public function userLogin(Request $request){
            Config::set('jwt.user', 'App\User'); 
            Config::set('auth.providers.users.model', \App\User::class);
            $credentials = $request->only('email', 'password');
            $token = null;
            try {
                if (!$token = JWTAuth::attempt($credentials)) {
                    return response()->json([
                        'response' => 'error',
                        'message' => 'invalid_email_or_password',
                    ]);
                }
            } catch (JWTAuthException $e) {
                return response()->json([
                    'response' => 'error',
                    'message' => 'failed_to_create_token',
                ]);
            }
            return response()->json([
                'response' => 'success',
                'result' => [
                    'token' => $token,
                    'message' => 'I am front user',
                ],
            ]);
        }
    
        public function adminLogin(Request $request){
            Config::set('jwt.user', 'App\Admin'); 
            Config::set('auth.providers.users.model', \App\Admin::class);
            $credentials = $request->only('email', 'password');
            $token = null;
            try {
                if (!$token = JWTAuth::attempt($credentials)) {
                    return response()->json([
                        'response' => 'error',
                        'message' => 'invalid_email_or_password',
                    ]);
                }
            } catch (JWTAuthException $e) {
                return response()->json([
                    'response' => 'error',
                    'message' => 'failed_to_create_token',
                ]);
            }
            return response()->json([
                'response' => 'success',
                'result' => [
                    'token' => $token,
                    'message' => 'I am Admin user',
                ],
            ]);
        }
    }
    

    希望对你有帮助。

    【讨论】:

    • 欢迎提供解决方案的链接,但请确保您的答案在没有它的情况下有用:add context around the link 这样您的其他用户就会知道它是什么以及为什么会出现,然后引用最相关的您链接到的页面的一部分,以防目标页面不可用。
    • @AmrAbdelRahman 非常感谢您花时间重播。我做了和你一样的事情,但是@me 控制器呢,如文档中所示return response()->json( $user = auth()->user() ); 我现在可以获得第一个用户信息,但第二个用户来自{} 空数组你能帮我清除这个吗
    • 当然,你只会得到当前用户尝试登录($user = auth()->user())!!您想获得所有用户吗?
    • 不只是登录用户步骤,因为我尝试postman 我先试试这个api/auth/userlogin 很好得到token 然后尝试这个api/auth/user/me 得到用户信息然后下一步尝试例如,管理员 api/auth/adminlogin 得到了 token 然后尝试 api/auth/admin/me 得到了 {} 空数组,这正是发生的事情
    • 现在,我明白你发生了什么事。嗯,请检查驱动程序,控制器,路线,型号!
    【解决方案2】:

    首先让我感谢@AmrAbdelRahman 的努力和时间。

    我的问题是应用程序总是使用我的default authentication "guard",因为我的默认设置是这样的

    'defaults' => [
            'guard'     => 'api',
            'passwords' => 'users',
        ],
    

    所以每次我尝试验证作为驱动程序的另一个用户时,默认验证期间失败的驱动程序是api,在这种情况下它应该使用driver

    在我的情况下,我所做的是在 App\Providers\AppServiceProvider 下的 boot 下制作一个切换器,如下所示

    $this->app['router']->matched(function (\Illuminate\Routing\Events\RouteMatched $e) {
                $route = $e->route;
                if (!array_has($route->getAction(), 'guard')) {
                    return;
                }
                $routeGuard = array_get($route->getAction(), 'guard');
                $this->app['auth']->resolveUsersUsing(function ($guard = null) use ($routeGuard) {
                    return $this->app['auth']->guard($routeGuard)->user();
                });
                $this->app['auth']->setDefaultDriver($routeGuard);
            });
    

    现在在我的情况下,如果$guard =api 它将读取guard 并正确运行,如果它是driver,它将使用新的guard 并按预期运行。希望这对将来的某些人有所帮助。

    【讨论】:

      【解决方案3】:

      config/auth.php 中的提供者无需更改。

      您可以如下更改每个控制器中的__construct 函数。以便 jwt 知道要验证哪个模型。

      DriverController

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

      【讨论】:

      • 你能解释一下吗?
      猜你喜欢
      • 2019-08-28
      • 2017-11-13
      • 2022-01-03
      • 2020-04-22
      • 2022-01-18
      • 1970-01-01
      • 1970-01-01
      • 2020-02-29
      • 2020-12-26
      相关资源
      最近更新 更多