美文网首页
Laravel 框架下多用户分表怎么实现认证

Laravel 框架下多用户分表怎么实现认证

作者: 晨曦入诗 | 来源:发表于2021-06-18 10:09 被阅读0次

    1、服务提供者配置

    多用户认证,实现逻辑如下:

    'guards' => [
        'admins' => [
            'driver' => 'jwt',
            'provider' => 'admins',
        ],
    
        'api' => [
            'driver' => 'jwt',
            'provider' => 'students',
        ],
        'teachers' => [
            'driver' => 'jwt',
            'provider' => 'teachers',
        ],
    ],
    
    
    'providers' => [
        'admins' => [
            'driver' => 'eloquent',
            'model' => App\Model\Admin::class,
        ],
        'students' => [
            'driver' => 'eloquent',
            'model' => App\Model\Student::class,
        ],
        'teachers' => [
            'driver' => 'eloquent',
            'model' => App\Model\Teacher::class,
        ]
    ],
    

    2、关于 dingo 中间件不支持多用户

    我是这么处理的,在用 dingo 的 api.auth 之前 加上自己写的用于切换 guard 的中间件 如下:

    添加中间件
    <?php
    
    namespace App\Http\Middleware;
    
    use Closure;
    
    class ChangeAuthGuard
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
    
        public function handle($request, Closure $next, $guard)
        {
            app()->singleton('auth.driver', function ($app) use($guard) {
                return $app['auth']->guard($guard);
            });
    
            return $next($request);
        }
    }
    
    注册中间件
    App\Http\Kernel
    protected $routeMiddleware = [
            'guard' => Middleware\ChangeAuthGuard::class,
            'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
    ]
    
    路由中使用注册的中间件
    $api->group(['middleware' => ['guard:admin','api.auth']],function ($api){
    // admin为你在auth配置文件 guards数组中定义的选项
    

    3、JWT 的 token 过期后抛出的异常不是过期异常

    关于 tymon/jwt-auth 的 token 过期后抛出的异常不是过期异常的处理:

    public function render($request, Exception $exception)
        {
            // detect instance
            if ($exception instanceof UnauthorizedHttpException) {
                // detect previous instance
                if ($exception->getPrevious() instanceof TokenExpiredException) {
                    return response()->json(['error' => 'TOKEN_EXPIRED'], $exception->getStatusCode());
                } else if ($exception->getPrevious() instanceof TokenInvalidException) {
                    return response()->json(['error' => 'TOKEN_INVALID'], $exception->getStatusCode());
                } else if ($exception->getPrevious() instanceof TokenBlacklistedException) {
                    return response()->json(['error' => 'TOKEN_BLACKLISTED'], $exception->getStatusCode());
                } else {
                    return response()->json(['error' => "UNAUTHORIZED_REQUEST"], 401);
                }
            }
            return parent::render($request, $exception);
        }
    

    4、角色隔离

    • 1、更改相应的 Model 文件:
      App\Models\User
    <?php
    namespace App\Models;
    
    use Illuminate\Notifications\Notifiable;
    use Illuminate\Foundation\Auth\User as Authenticatable;
    use Tymon\JWTAuth\Contracts\JWTSubject;
    
    class User extends Authenticatable implements JWTSubject
    {
        use Notifiable;
    
        /**
         * The attributes that are mass assignable.
         *
         * @var array
         */
        protected $fillable = [
            'name', 'email', 'password',
        ];
    
        /**
         * The attributes that should be hidden for arrays.
         *
         * @var array
         */
        protected $hidden = [
            'password', 'remember_token',
        ];
    
        /**
         * 获取会储存到 jwt 声明中的标识
         * @return mixed
         */
        public function getJWTIdentifier()
        {
            return $this->getKey();
        }
    
        /**
         * 返回包含要添加到 jwt 声明中的自定义键值对数组
         * @return array
         */
        public function getJWTCustomClaims()
        {
            return ['role' => 'user'];
        }
    }
    

    App\Models\Admin

    <?php
    
    namespace App\Models;
    
    use Illuminate\Notifications\Notifiable;
    use Illuminate\Foundation\Auth\User as Authenticatable;
    use Tymon\JWTAuth\Contracts\JWTSubject;
    
    class Admin extends Authenticatable implements JWTSubject
    {
        use Notifiable;
    
        /**
         * The attributes that are mass assignable.
         *
         * @var array
         */
        protected $fillable = [
            'name', 'email', 'password',
        ];
    
        /**
         * The attributes that should be hidden for arrays.
         *
         * @var array
         */
        protected $hidden = [
            'password', 'remember_token',
        ];
    
        /**
         * 获取会储存到 jwt 声明中的标识
         * @return mixed
         */
        public function getJWTIdentifier()
        {
            return $this->getKey();
        }
    
        /**
         * 返回包含要添加到 jwt 声明中的自定义键值对数组
         * @return array
         */
        public function getJWTCustomClaims()
        {
            return ['role' => 'admin'];
        }
    }
    
    • 2、创建中间件检测当前 token 对应的是哪个平台 php artisan make:middleware JWTRoleAuth
    <?php
    
    namespace App\Http\Middleware;
    
    use Closure;
    use Tymon\JWTAuth\Exceptions\JWTException;
    use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
    use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
    
    class JWTRoleAuth extends BaseMiddleware
    {
        /**
         * JWT 检测当前登录的平台
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @param  null $role
         * @return mixed
         */
        public function handle($request, Closure $next, $role = null)
        {
            try {
                // 解析token角色
                $tokenRole = $this->auth->parseToken()->getClaim('role');
            } catch (JWTException $e) {
                /**
                 * token解析失败,说明请求中没有可用的token。
                 * 为了可以全局使用(不需要token的请求也可通过),这里让请求继续。
                 * 因为这个中间件的责职只是校验token里的角色。
                 */
                return $next($request);
            }
            // 判断token角色。
            if ($tokenRole != $role) {
                throw new UnauthorizedHttpException('jwt-auth', 'User role error');
            }
            return $next($request);
        }
    }
    
    • 3、在 router/api.php 文件中创建路由信息
    # 普通用户登录
    Route::group(['prefix' => 'auth'], function () {
        Route::post('login', 'AuthController@login');
        Route::post('logout', 'AuthController@logout');
        Route::post('refresh', 'AuthController@refresh');
        Route::post('me', 'AuthController@me')->name('me')->middleware(['jwt.role:user', 'jwt.auth']);
    });
    
    # 后台用户登录
    Route::group(['prefix' => 'admin', 'namespace' => 'Admin'], function () {
        Route::post('login', 'LoginController@login');
        Route::post('logout', 'LoginController@logout');
        Route::post('refresh', 'LoginController@refresh');
        Route::post('me', 'LoginController@me')->middleware(['jwt.role:admin', 'jwt.auth'])->name('me');
    });
    

    相关文章

      网友评论

          本文标题:Laravel 框架下多用户分表怎么实现认证

          本文链接:https://www.haomeiwen.com/subject/jnlkyltx.html