Dcat-admin實現一個賬號只能同時登入一次

Latent發表於2021-04-21

具體思路很簡單-當使用者登入刪除上次登入的session並記錄現在登入的session

文件上所寫 我們可以重寫父類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快取入token
     */
    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 最後在.env中將SESSION_DRIVER更改為redis驅動

本作品採用《CC 協議》,轉載必須註明作者和本文連結
不成大牛,不改個簽

相關文章