Dcat-admin实现一个账号只能同时在线一次

Laravel框架
489
0
0
2022-04-09
标签   Dcat Admin
具体思路很简单-当用户登录删除上次登录的session并记录现在登录的session id

文档上所写 我们可以重写父类AuthController的方法

namespace App\Admin\Controllers;
use Dcat\Admin\Controllers\AuthController as BaseAuthController;
class AuthController extends BaseAuthController
{
  // 自定义登录view模板
  protected $view = 'admin.login';

    // 重写你的登录页面逻辑
  public function getLogin(Content $content){
    ...
  }

    ...
}

查看继承的父类BaseAuthController,可以看到验证登录的方法

/**
     * Handle a login request.
     *
     * @param Request $request
     *
     * @return mixed
     */ 
    public function postLogin(Request $request){
        $credentials = $request->only([$this->username(), 'password']);
        $remember = (bool) $request->input('remember', false);
       /** @var \Illuminate\Validation\Validator $validator */
        $validator = Validator::make($credentials, [$this->username()   => 'required','password'          => 'required',]);
        if ($validator->fails()) {
            return $this->validationErrorsResponse($validator);
        }
        if ($this->guard()->attempt($credentials, $remember)) {
            //验证成功后执行响应成功
            return $this->sendLoginResponse($request);
        }
        return $this->validationErrorsResponse([$this->username() => $this->getFailedLoginMessage(),]);
    }

验证登录成功后执行sendLoginResponse方法并会生成一个session令牌

 /**
     * Send the response after the user was authenticated.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return \Symfony\Component\HttpFoundation\Response
     */
    protected function sendLoginResponse(Request $request){
        $request->session()->regenerate();

        return $this->redirectToIntended($this->redirectPath(),trans('admin.login_successful'));
    }

在新创建的子类里面重写该方法

/**
     * Send the response after the user was authenticated.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return \Symfony\Component\HttpFoundation\Response
     */
    protected function sendLoginResponse(Request $request){
        //删除旧的会话信息
        $this->delSessionForRedis();
        $request->session()->regenerate();
        //存储新的会话信息
        $this->setSessionForRedis();
        return $this->redirectToIntended($this->redirectPath(),trans('admin.login_successful'));
    }

    /**
     * 将会话id缓存入redis
     */
    private function setSessionForRedis(){
        Redis::set('session_id_'.auth()->id(),'_database__cache:'.session()->getId());
    }

    /**
     * 清理旧会话
     */
    private function delSessionForRedis(){
        $key =  Redis::get('session_id_'.auth()->id());
        if($key){$key =  '_'.trim($key,"_database_");
        Redis::del($key);
    }
}

实现了两步删除上一次登录的session、记录当前的session会话id 最后在.env中将SESSION_DRIVER更改为redis驱动

Dcat-admin实现一个账号只能同时在线一次