【转载】Laravel 中的Remember Me

转自:https://learnku.com/articles/32712

在 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,如果有那么就会尝试解析是否能够获得用户,如果能,那么证明用户已登录,否则登录失败。

点赞
  1. AllInAce说道:
    Google Chrome Windows 10
    https://t.me/s/iGaming_live/4866
  2. LuckyBandit说道:
    Google Chrome Windows 10
    https://t.me/s/atom_official_casino
  3. HighRollerMage说道:
    Google Chrome Windows 10
    http://images.google.ki/url?q=https://t.me/s/officials_7k/1022
  4. HighRollerMage说道:
    Google Chrome Windows 10
    В лабиринте азарта, где каждый ресурс стремится привлечь обещаниями простых выигрышей, рейтинг казино является той самой картой, которая направляет мимо дебри подвохов. Игрокам ветеранов и дебютантов, которые пресытился из-за фальшивых обещаний, это средство, чтоб ощутить настоящую выплату, как ощущение золотой монеты в пальцах. Минус лишней болтовни, только реальные площадки, где отдача не только цифра, а реальная удача.Составлено на основе яндексовых поисков, словно паутина, что вылавливает наиболее свежие тенденции на рунете. Тут минуя места для шаблонных трюков, всякий элемент как ход в покере, где подвох выявляется мгновенно. Профи видят: на стране стиль письма на подтекстом, где юмор скрывается под рекомендацию, помогает миновать рисков.В https://www.youtube.com/@Don8Play/posts этот список лежит словно открытая колода, приготовленный на раздаче. Зайди, коли хочешь почувствовать ритм подлинной ставки, без мифов плюс разочарований. Игрокам что любит вес выигрыша, это будто держать фишки на руках, минуя глядеть на экран.

发表回复

电子邮件地址不会被公开。必填项已用 * 标注