Multi Jwt Auth与Laravel和Mongodb

Beh*_*imi 5 php mongodb jwt laravel laravel-5

我有三种类型的Authenticatable模型,我需要为每个模型分别进行JWT身份验证.让我解释一下我的问题.

我使用MongoDB作为我的数据库,Laravel MongoDB是我使用的包.

User,Admin和,ServiceProvider是我的模特.

要在Laravel中使用JWT auth,我使用jwt-auth包.用户模型(集合)没问题.当我想将JWT与任何其他型号一起使用时它无法工作并user再次完成所有工作.

我搜索了很多,我发现要更改提供者用户模型我可以使用Config::set();如下方法,

Config::set('jwt.user', Admin::class);
Config::set('auth.providers.users.model', Admin::class);
Run Code Online (Sandbox Code Playgroud)

但对JWT认证没有影响.(我检查的价值'jwt.user',并'auth.providers.users.model'Config::get()方法,并返回它,它已被更改为'App\Admin').

需要说明的是,根据软件包的文档,我的代码尽可能简单.这是我的UserController代码:

class UserController extends Controller
{
    public function login(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'email' => 'required|string|email|max:255',
            'password' => 'required|min:6'
        ]);

        if ($validator->fails()) {
            return response()->json($validator->errors());
        }

        $credentials = $request->only('email', 'password');

        try {
            if (!$token = JWTAuth::attempt($credentials)) {
                return response()->json(['error' => 'invalid_credentials'], 401);
            }
        } catch (JWTException $e) {
            return response()->json(['error' => 'could_not_create_token'], 500);
        }

        $user = User::where('email', $request->email)->first();
        return response()->json([
            'user' => $user,
            'token' => $token
        ]);
    }

    public function register(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'email' => 'required|string|email|max:255|unique:users',
            'phone' => 'required|valid_phone|unique:users',
            'password' => 'required|min:6',
            'first_name' => 'required',
            'last_name' => 'required',
        ]);

        if ($validator->fails()) {
            return response()->json($validator->errors());
        }

        User::create([
            'phone' => $request->get('phone'),
            'first_name' => $request->get('first_name'),
            'last_name' => $request->get('last_name'),
            'city_abbr' => $request->get('city_abbr'),
            'email' => $request->get('email'),
            'password' => bcrypt($request->get('password')),
        ]);
        $user = User::first();
        $token = JWTAuth::fromUser($user);

        return response()->json([
            'user' => $user,
            'token' => $token
        ]);

    }

}
Run Code Online (Sandbox Code Playgroud)

我的AdminController:

class AdminController extends Controller
{

    public function login(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'email' => 'required|string|email|max:255',
            'password' => 'required|min:6'
        ]);

        if ($validator->fails()) {
            return response()->json($validator->errors());
        }

        $credentials = $request->only('email', 'password');

        Config::set('jwt.user', Admin::class);
        Config::set('auth.providers.users.model', Admin::class);

        try {
            if (!$token = JWTAuth::attempt($credentials)) {
                return response()->json(['error' => 'invalid_credentials'], 401);
            }
        } catch (JWTException $e) {
            return response()->json(['error' => 'could_not_create_token'], 500);
        }

        $admin = Admin::where('email', $request->email)->first();
        return response()->json([
            'admin' => $admin,
            'token' => $token
        ]);
    }

    public function register(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'email' => 'required|string|email|max:255|unique:admins',
            'phone' => 'required|valid_phone|unique:admins',
            'password' => 'required|min:6',
            'name' => 'required',
        ]);

        if ($validator->fails()) {
            return response()->json($validator->errors());
        }

        $admin = Admin::create([
            'phone' => $request->get('phone'),
            'name' => $request->get('name'),
            'access' => $request->get('access'),
            'email' => $request->get('email'),
            'password' => bcrypt($request->get('password')),
        ]);
        Config::set('jwt.user', Admin::class);
        Config::set('auth.providers.users.model', Admin::class);

        $token = JWTAuth::fromUser($admin);

        return response()->json([
            'admin' => $admin,
            'token' => $token
        ]);

    }

}
Run Code Online (Sandbox Code Playgroud)

我在某个地方错了吗?这有什么解决方案吗?

更新:

为了确保MongoDB的功能,我用关系数据库测试了上述所有操作,实际上是MySQL.没有改变!

JWTAuth生成令牌,但是当我toUser使用任何模型运行方法时User,它返回null!

任何解决方案将不胜感激.

小智 2

以下是使用 JWT 将多重身份验证功能添加到我的项目中所必须执行的操作。

  1. tymon JWT auth包中。在 中JWTAuthServiceProvider,将Tymon\JWTAuth\JWTAuth定义Tymon\JWTAuth\Providers\User\UserInterface类型从更改singletonbindinbootBindings方法。

  2. 定义了一个新的中间件,下面的代码是它的handle方法:

    public function handle($request, Closure $next){
            if (!$request->header('Auth-Type')) {
                return response()->json([
                    'success' => 0,
                    'result' => 'auth type could not found!'
                ]);
            }
        switch ($request->header('Auth-Type')) {
        case 'user':
            $auth_class = 'App\User';
            break;
    
        case 'admin':
            $auth_class = 'App\Admin';
            break;
    
        case 'provider':
            $auth_class = 'App\ServiceProvider';
            break;
    
        default:
            $auth_class = 'App\User';
    
    }
    
    if (!Helpers::modifyJWTAuthUser($auth_class))
        return response()->json([
            'status' => 0,
            'error' => 'provider not found!'
        ]);
    
    return $next($request);    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 定义了一个名为modifyJWTAuthUserin 的函数Helpers,这是它的内部:

    public static function modifyJWTAuthUser($user_class){
    if (!$user_class ||
        (
            $user_class != 'App\User' &&
            $user_class != 'App\Admin' &&
            $user_class != 'App\ServiceProvider'
        ))
        return false;
    
    try {
        Config::set('jwt.user', $user_class);
        Config::set('auth.providers.users.model', $user_class);
    
        app()->make('tymon.jwt.provider.user');
        return true;
    } catch (\Exception $e) {
        return false;
    }    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 介绍了另一个$routeMiddleware像下面这样的Kernel.php

    ... 'modify.jwt.auth.user' => ChangeJWTAuthUser::class,

  5. 最后一步,将'modify.jwt.auth.user'中间件添加到您想要的路由中。

但即使执行了这些步骤,您也一定遇到了新问题。这是关于通过登录中的凭据获取身份验证令牌并从令牌获取身份验证用户。(似乎更改配置值不会影响JWTAuth::attempt($credentials)$this->auth->authenticate($token)

解决从token获取auth用户的问题:

创建一个新的中间件CustomGetUserFromToken which extends of Tymon'sjwt.auth middleware, I meanGetUserFromToken and in line 35, and **replace**$user = $this->auth->authenticate($token); with$user = JWTAuth::toUser($token);`

并解决登录问题中通过凭据获取身份验证令牌的问题:

首先,找到身份验证用户,然后使用Hash::check()方法检查用户是否存在并验证密码,如果这些条件返回 true,则从用户生成令牌。这是登录代码:

$admin = Admin::where('email', $request->email)->first();
if (!$admin || !Hash::check($request->get('password'), $admin->password)) {
    return response()->json([
        'success' => '0',
        'error' => 'invalid_credentials'
    ], 401);
}
Run Code Online (Sandbox Code Playgroud)

我不确定这种方式,但我认为在找到正确的方法之前这是正确的!

结论:

在 Laravel 中拥有多 JWT 身份验证功能也许还有很多其他方法可以实现,但我确实喜欢这个并分享它以提供帮助。

我认为这个问题唯一重要的一点是app()->make('tymon.jwt.provider.user');,在配置值更改后重新创建用户提供程序的能力。

任何其他解决方案将不胜感激。