慕容的工作随笔

慕容的工作随笔

记录学习和工作

【转载】将Laravel中的rember_token变为一次性token

转自:https://www.jianshu.com/p/ef7b1bce1e1c

前言

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();
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">is_null</span><span class="token punctuation">(</span><span class="token variable">$user</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span> <span class="token function">is_null</span><span class="token punctuation">(</span><span class="token variable">$recaller</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token variable">$user</span> <span class="token operator">=</span> <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">userFromRecaller</span><span class="token punctuation">(</span><span class="token variable">$recaller</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$user</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token comment">// 重新生成token</span>
            <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">cycleRememberToken</span><span class="token punctuation">(</span><span class="token variable">$user</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

            <span class="token comment">// 重新定义用户</span>
            <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">setUser</span><span class="token punctuation">(</span><span class="token variable">$user</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

            <span class="token comment">// 刷新cookie</span>
            <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">queueRecallerCookie</span><span class="token punctuation">(</span><span class="token variable">$user</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

            <span class="token comment">// 更新session</span>
            <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">updateSession</span><span class="token punctuation">(</span><span class="token variable">$user</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">getAuthIdentifier</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

            <span class="token comment">// 退出登录事件</span>
            <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">fireLoginEvent</span><span class="token punctuation">(</span><span class="token variable">$user</span><span class="token punctuation">,</span> <span class="token boolean constant">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">user</span> <span class="token operator">=</span> <span class="token variable">$user</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

当完成了这一步,你的token就能够随着登录而重新刷新了。
因为是修改的源码,显然这时不可取的。笔者已向taylor大神发送了邮件,表达了这个看法,如果taylor大神认可的的话,可能再接下来的版本中就能够看到这一项更新了。
当然,如果你现在就要使用的话,不建议修改源码。建议自己写一个记住密码的功能。

评论 (0)

还没有评论,来做第一个吧。

发表评论

提交后需管理员审核通过后显示