Lravel 5.4:在两个表上具有多重身份验证的JWT API,一个起作用,另一个不起作用 [英] Lravel 5.4: JWT API with multi-auth on two tables one works the other not
问题描述
我正在使用...
- Laravel 5.4
- tymon/jwt-auth:1.0.0-rc.2
我有两个身份验证API的应用程序,一个是customers
,另一个是drivers
,每个都有自己的表.
I have application with two authentications API one is customers
and the other is drivers
each one has it's own table.
现在让我简要介绍一下JWT
软件包的安装以及我对此所做的更新.
now let me describe shortly JWT
package installation and the updates I did on it.
- 我按照 JWT 文档中所述安装了软件包完全是
- 现在进入快速开始,这里我更新了两个
Models
一个是User
,另一个是Driver
. -
再次来到
Configure Auth guard
,我使用了两个guards
的配置,让我展示了auth.php
的快照.
- I installed the package as described in the JWT documents exactly.
- Now comes to the quick start here I updated two
Models
one is theUser
and the secondDriver
. Comes here to the
Configure Auth guard
again I used the configuration for the twoguards
let me show a snapshot of myauth.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
Now continue the application with authentication routes
here is my Routes
for the two Models
这是User
和Driver
路线
Route::group( [
'prefix' => 'auth',
'middleware' => 'api'
], function () {
.......
});
Route::group( [
'prefix' => 'driver',
'middleware' => 'api'
], function () {
.......
});
- 现在是
AuthController
- Now comes the
AuthController
construct
就是这样写的.
public function __construct()
{
$this->middleware('auth:api', ['except' => ['login']]);
}
我找到了一些文章,建议做这样的事情来在我们拥有的两个模型之间进行切换.
I found some article that suggest to make it something like this to switch between the two models we have.
所以我的控制器在这里看起来像现在.
so here with my controller looks like now.
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();
}
现在正在发生,我遇到的问题
Now with is happening and the problems I faced
现在,驱动程序api
仅作为login
工作.
Now the driver api
is working as login
only Ex.
localhost:8000/api/driver/login
正常
但是当尝试像这样获得驱动程序用户id
but when try to get the driver user id
like this
localhost:8000/api/driver/me
它返回空array
第二个问题来了.
Second Issue comes.
interface
中用于Ex的使用登录. http://localhost:8000/login
它会返回登录屏幕而没有任何错误,因为登录信息正确,但是auth.php
中的defaults
是'guard'=>'api'
,如果我将其更改为'guard'=>'web'
则可以正确登录.
the use login from the interface
for Ex. http://localhost:8000/login
it returns back to the login screen without any errors becouse the login information is right but the defaults
in the auth.php
is 'guard'=>'api'
if I change it to 'guard'=>'web'
it do the login correctly.
甚至是User API
. localhost:8000/api/auth/login
始终返回
{
"response": "error",
"message": "invalid_email_or_password"
}
更新
我解决了一半 我将
AuthController
更新为类似这样的内容.
I solved half the way I updated the
AuthController
to be something like this.
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',
],
如果URL请求为localhost:8000/api/driver/login
,则我需要将'guard'=>'api'
切换为'guard'=>'driver-api'
;如果URL请求为localhost:8000/api/customer/login
,则需要将'guard'=>'api'
切换为'guard'=>'api'
.
here I need to switch the 'guard'=>'api'
to be 'guard'=>'driver-api'
in case if URL request is localhost:8000/api/driver/login
and 'guard'=>'api'
in case if URL request is localhost:8000/api/customer/login
any way to do this.
更新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 [];
}
我需要一些帮助,请给我一些想法.
I need some help, Ideas please.
推荐答案
首先,我感谢您@AmrAbdelRahman所做的努力和时间.
First let me thank you @AmrAbdelRahman for you efforts and your time.
我的问题是应用程序总是使用我的default authentication "guard"
,因为我的默认外观是这样的
My problem was the application always using my default authentication "guard"
as my default looks like that
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
因此,每次我尝试对另一个用户进行驱动程序身份验证时,在默认身份验证期间失败的驱动程序均为api
,在这种情况下,应使用driver
.
so every time I try to authenticate the other user which was the driver it fails during the default authenticate is api
and the it should using driver
in this case.
在我的情况下,我要做的是在boot
下的App\Providers\AppServiceProvider
中制作一个切换器,这是这样的样子
what I did in my case was making a switcher in my App\Providers\AppServiceProvider
under the boot
here is how it looks like
$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
并按预期进行操作.希望这会在将来对您有所帮助.
Now in my case if the $guard =api
it will read that guard
and act correctly and if it's driver
it will use the new guard
and act as expected. Hope this will help some one in future.
这篇关于Lravel 5.4:在两个表上具有多重身份验证的JWT API,一个起作用,另一个不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!