Lravel 5.4:在两个表上使用多个身份验证的JWT API一个不工作

时间:2018-03-10 17:42:03

标签: php laravel authentication jwt laravel-5.4

我正在使用......

  • 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文档中的{p> 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使用Ex。

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

但是当试图让驱动程序用户id像这样

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

  

第二期出现。

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

甚至是Ex的User APIlocalhost: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'以防万一网址请求为localhost:8000/api/driver/login,{}为'guard'=>'api'以防网址请求为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 [];
        }

我需要一些帮助,请点赞。

3 个答案:

答案 0 :(得分:2)

我在jwt

中使用多个auth的例子

我有2个型号: 用户 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',
            ],
        ]);
    }
}

我希望能帮到你。

答案 1 :(得分:2)

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

您可以如下更改每个控制器中的__construct功能。这样jwt知道要验证哪种模型。

DriverController

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

答案 2 :(得分:0)

首先让我感谢@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,它将使用新的DELETE FROM DevProj WHERE (DeveloperID, ProjectID, WorkDate) = (1, 2, '2018-01-01'); 并按预期行事。希望这将有助于将来的某些人。