前言
Laravel开箱即用的用户登录注册甚是好用,如果你还不知道如何使用请移步用户认证文档。
但笔者发现一个问题,remeber_token的问题。remeber_token只要在用户选择了记住密码
的按钮,那么只要用户不退出,那么这个token将持续五年,意思就是在五年之内,你都可以拿着这个remeber_token
去登录这个账号。显然,这是不安全的。
而参照了大多数网站的做法,应该是每一次登录,即刷新这个token,让一个token的变为一次性的事物。这样能增强登录验证的安全性。
那在laravel中怎么做呢?
笔者翻阅了源码,做了诸多实验之后,终于是做到了。但笔者是修改的源码,如果想要在生产环境中使用,不建议这么做。
本文主要是为了带大家疏通思路,看一下源码。
解决方案
首先查看登录的源码部分,由于多层调用,建议使用IDE快速命中。
登陆的核心逻辑在vendor/laravel/framework/src/Illuminate/Auth/SessionGuard.php
之中,其中的functionattempt
是其具体的实现逻辑。同文件目录下的functionlogin
是在用户比对完成后,添加session的部分,这一个位置比较重要。
然后,查看auth中间件的逻辑。在vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php
中,可以看到中间的调用逻辑。
其最终调用的是vendor/laravel/framework/src/Illuminate/Auth/SessionGuard.php
的functionuser()
,
其中
$recaller = $this->recaller();
的逻辑,是使用request中的cookieremeber_token
与现有的数据进行比对,当比对成功返回user的信息
,再将其保存在session中。这样就实现了,remeber_token的登录了。
但需要注意的是此时,remeber_token没有变化,这时如果想要做到remeber_token跟随登录后,进行改变的话,那么我们就需要在functionuser()
做一点手脚了。
我们可以模仿登录,让remeber_token能够进行改变。那么只需要将login的逻辑拿过来就ok了。
将functionuser
改写如下:
...
// If the user is null, but we decrypt a "recaller" cookie we can attempt to
// pull the user data on that cookie which serves as a remember cookie on
// the application. Once we have a user we can return it to the caller.
$recaller = $this->recaller();
if (is_null($user) && ! is_null($recaller)) {
$user = $this->userFromRecaller($recaller);
if ($user) {
// 重新生成token
$this->cycleRememberToken($user);
// 重新定义用户
$this->setUser($user);
// 刷新cookie
$this->queueRecallerCookie($user);
// 更新session
$this->updateSession($user->getAuthIdentifier());
// 退出登录事件
$this->fireLoginEvent($user, true);
}
}
return $this->user = $user;
}
当完成了这一步,你的token就能够随着登录而重新刷新了。
因为是修改的源码,显然这时不可取的。笔者已向taylor大神发送了邮件,表达了这个看法,如果taylor大神认可的的话,可能再接下来的版本中就能够看到这一项更新了。
当然,如果你现在就要使用的话,不建议修改源码。建议自己写一个记住密码的功能。