Laravel 5.4:在两个表上具有多重身份验证的 JWT API 一个有效,另一个无效
Posted
技术标签:
【中文标题】Laravel 5.4:在两个表上具有多重身份验证的 JWT API 一个有效,另一个无效【英文标题】:Lravel 5.4: JWT API with multi-auth on two tables one works the other not 【发布时间】:2018-08-19 02:34:06 【问题描述】:我正在使用...
Laravel 5.4 tymon/jwt-auth : 1.0.0-rc.2我的应用程序有两个身份验证 API,一个是 customers
,另一个是 drivers
,每个都有自己的表。
现在让我简要介绍一下JWT
软件包的安装以及我对它所做的更新。
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
这是User
和Driver
路由
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 [];
还有User
Model
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 [];
我需要一些帮助,请出主意。
【问题讨论】:
【参考方案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,
]]);
【讨论】:
你能解释一下吗?以上是关于Laravel 5.4:在两个表上具有多重身份验证的 JWT API 一个有效,另一个无效的主要内容,如果未能解决你的问题,请参考以下文章
Laravel - 具有多重身份验证的未经身份验证的重定向问题