Laravel CSRF 保护
Posted
技术标签:
【中文标题】Laravel CSRF 保护【英文标题】:Laravel CSRF protection 【发布时间】:2018-05-27 01:27:58 【问题描述】:我知道什么是 CSRF 攻击,并且我已经阅读了有关它的文档,但是我无法深入理解 CSRF 保护的工作原理,并且有一些我找不到的一般性问题。
在documentation 中说 Laravel 会自动为
...由应用程序管理的每个活动用户会话。
-
它在哪里创建令牌(代码的哪一部分触发它)?
创建后的令牌存储在 cookie 中的什么位置?在会话中?如何提取并查看已存储的内容?这一切实际上是由
session.php
控制的吗?
这是什么意思,当我重新加载页面时,令牌是否仍与 session.php
相同,默认生命周期为 120 分钟?
如果我将domain
属性设置为"." . env('APP_URL')
,当我导航到由同一应用处理的子域时,该cookie 会发生什么情况?
因此,一旦创建令牌并将其存储在某处,当发出请求时,我必须向表单提供 csrf_token()
隐藏属性,或者将其生成为元字段并重定向到我的 JS 文件,如果我是做一个 AJAX 请求。
那么当我实际发出请求时,底层会发生什么?请求生成csrf_token()
,Laravel 对 cookie 进行加密,Laravel 检查发送的 cookie 是否与 session 中的 cookie 相同。如果是,则表示请求有效,如果不是,则抛出TokenMissmatchException
?
这是否意味着 cookie 生命周期内的每个请求都将具有相同的令牌?
Laravel 对请求和响应 cookie 的加密方式不同吗?如果我从 EncryptCookies
类中的 cookie 加密中排除令牌,我会得到相同的令牌,但是当我离开它时,哈希值是不同的。
在请求数据中提供_token
与作为X-CSRF-TOKEN
标头的转发令牌有何不同?如果我看到它们未加密,Laravel 如何验证它们?他们在请求后会被加密吗?
【问题讨论】:
这里有很多不同的问题,不适用于本网站的格式:虽然答案可能涵盖所有问题,但很容易结束有多个答案,每个答案都涵盖不同的方面,或者页面演变为讨论和修改。如果你能把问题稍微集中一点会更好,必要时可以提出多个问题。 也许这个答案会帮助你了解 csrf ***.com/a/51673924/4701635的内部逻辑 【参考方案1】:它在哪里创建令牌(代码的哪一部分触发它)?
查看帮助文件后
/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php
其中定义了csrf_token()
辅助方法,它调用了token方法
/vendor/laravel/framework/src/Illuminate/Session/Store.php
如果您检查调用regenerateToken()
的start()
,如果_token
尚未设置,它会使用_token
的密钥将随机40 个字符串保存到会话中
/**
* Regenerate the CSRF token value.
*
* @return void
*/
public function regenerateToken()
$this->put('_token', Str::random(40));
创建后的令牌存储在 cookie 中的什么位置?在会话中?如何提取并查看已存储的内容?这一切实际上都是由 session.php 控制的吗?
令牌存储在会话中,您可以使用session('_token')
提取它。会话过期时间控制在session.php
中使用
'lifetime' => env('SESSION_LIFETIME', 120),
'expire_on_close' => false,
这是什么意思,当我重新加载页面时,令牌仍然与 session.php 的默认生命周期相同吗? 120 分钟?
如果您在/vendor/laravel/framework/src/Illuminate/Session/Store.php
中检查start()
/**
* Start the session, reading the data from a handler.
*
* @return bool
*/
public function start()
$this->loadSession();
if (! $this->has('_token'))
$this->regenerateToken();
return $this->started = true;
如果会话没有_token
,则重新生成令牌。所以_token
在会话到期之前都是一样的
【讨论】:
【参考方案2】:在我的例子中,从 .env 中删除 APP_URL=http://localhost 解决了 CSRF 令牌的问题。我没有为本地开发人员在 APP_URL 中配置固定值,因为我总是通过浏览器使用不同的主机名,有时还使用端口。
【讨论】:
以上是关于Laravel CSRF 保护的主要内容,如果未能解决你的问题,请参考以下文章