Laravel 中 “记住我” 原理分析 | 您所在的位置:网站首页 › 记住密码原理是什么 › Laravel 中 “记住我” 原理分析 |
在这篇文章中,我们分析一下 Laravel 中的“记住我” 功能是怎样实现的。 在 Laravel 为我们提供的默认登录中,为我们提供了“记住我”的选项,那么这一逻辑是怎样实现的呢? 登录首先在 LoginController中,引入了 Illuminate\Foundation\Auth\AuthenticatesUsers 这个 Trait。在这个 Trait 中有个 login 方法: public function login(Request $request) { $this->validateLogin($request); if (method_exists($this, 'hasTooManyLoginAttempts') && $this->hasTooManyLoginAttempts($request)) { $this->fireLockoutEvent($request); return $this->sendLockoutResponse($request); } if ($this->attemptLogin($request)) { return $this->sendLoginResponse($request); } $this->incrementLoginAttempts($request); return $this->sendFailedLoginResponse($request); }在这其中,登录判断在$this->attemptLogin($request)方法中: protected function attemptLogin(Request $request) { return $this->guard()->attempt( $this->credentials($request), $request->filled('remember') ); } SessionGuard在常规的 web 登录中,我们使用 Illuminate\Auth\SessionGuard 来处理登录。 public function attempt(array $credentials = [], $remember = false) { $this->fireAttemptEvent($credentials, $remember); $this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials); if ($this->hasValidCredentials($user, $credentials)) { $this->login($user, $remember); return true; } $this->fireFailedEvent($user, $credentials); return false; } public function login(AuthenticatableContract $user, $remember = false) { $this->updateSession($user->getAuthIdentifier()); if ($remember) { $this->ensureRememberTokenIsSet($user); $this->queueRecallerCookie($user); } $this->fireLoginEvent($user, $remember); $this->setUser($user); } protected function ensureRememberTokenIsSet(AuthenticatableContract $user) { if (empty($user->getRememberToken())) { $this->cycleRememberToken($user); } } protected function queueRecallerCookie(AuthenticatableContract $user) { $this->getCookieJar()->queue($this->createRecaller( $user->getAuthIdentifier().'|'.$user->getRememberToken().'|'.$user->getAuthPassword() )); } protected function createRecaller($value) { return $this->getCookieJar()->forever($this->getRecallerName(), $value); }从上面的代码中我们看到在attempt方法中,我们调用了login方法。在login方法中,如果$remember为true,那么就会调用ensureRememberTokenIsSet和queueRecallerCookie方法。 ensureRememberTokenIsSet方法的作用很简单,如果 users 表中的 remember_token 为空,那么生成一个60位长度的随机字符串,然后保存到 remember_token 字段中。 而在queueRecallerCookie方法中,首先会创建一个Recaller,其返回值为一个Cookie对象,如下: Cookie {#266 ▼ #name: "remember_web_59ba36addc2b2f9401580f014c7f58ea4e30989d" #value: "1|GI9K0OMvKvPFeWBjA3R8Kkyt7z0DB3wseJj0Pf87d4dAk5TNoDDkS8DNrjzZ|$2y$10$DXU1oUnRz.nzSqWHvuWZKuMTb4I9C46GIx6CYnkwtJNlHf.V4zu1C" #domain: null #expire: 1723619737 #path: "/" #secure: false #httpOnly: true -raw: false -sameSite: null -secureDefault: false }其中 value 由两个|隔开,第一部分可以表示user_id,第二部分是 users 表中的 remember_token 值,第三部分是用户的密码。在经过 App\Http\Middleware\EncryptCookies的处理下返回加密后的cookie,其 key 为 上面 Cookie 中的 name 字段。 检查用户是否登录那么我们怎样通过这个 cookie 来检查用户已经登录了呢?同样的在 SessionGuard 中有一个 user方法: public function user() { if ($this->loggedOut) { return; } if (! is_null($this->user)) { return $this->user; } $id = $this->session->get($this->getName()); if (! is_null($id) && $this->user = $this->provider->retrieveById($id)) { $this->fireAuthenticatedEvent($this->user); } if (is_null($this->user) && ! is_null($recaller = $this->recaller())) { $this->user = $this->userFromRecaller($recaller); if ($this->user) { $this->updateSession($this->user->getAuthIdentifier()); $this->fireLoginEvent($this->user, true); } } return $this->user; }用户在请求的过程中会判断cookie中是否有remember_web_xxxx 的key,如果有那么就会尝试解析是否能够获得用户,如果能,那么证明用户已登录,否则登录失败。 本作品采用《CC 协议》,转载必须注明作者和本文链接 There's nothing wrong with having a little fun. |
CopyRight 2018-2019 实验室设备网 版权所有 |