Laravel CSRF保护

10

我知道什么是 CSRF 攻击,并阅读了相关文档,但我难以深入理解 CSRF 保护的工作原理,并有一些通用问题无法回答。

文档中,它说 Laravel 自动为应用程序管理的每个活动用户会话生成一个令牌。

... each active user session managed by the application.

  1. 令牌是在哪里创建的(代码的哪个部分触发了它)?
  2. 令牌在创建后存储在何处,在 cookie 中?在会话中?我如何提取和查看已存储的内容?所有这些是否由 session.php 控制?
  3. 当我重新加载页面时,这意味着什么,令牌是否仍然与 session.php 具有默认生存期 120 分钟相同?
  4. 当我导航到同一应用程序处理的子域时,如果我将我的 domain 属性设置为 "." . env('APP_URL'),那么该 cookie 会发生什么?

因此,一旦令牌已被创建并存储在某处,在进行请求时,我必须在表单中提供 csrf_token() 隐藏属性,或者将其生成为元字段并重定向到我的 JS 文件,如果我正在执行 AJAX 请求。

  1. 那么,在实际进行请求时会发生什么?请求生成 csrf_token(),Laravel 加密 cookie,Laravel 检查发送的 cookie 是否与会话中的 cookie 相同。如果是,则表示该请求有效;如果不是,则抛出 TokenMissmatchException

  2. 这是否意味着在 cookie 的生命周期内,每个请求都具有相同的令牌?

  3. Laravel 是否以不同方式加密请求和响应 cookie?如果我在 EncryptCookies 类中排除 cookie 加密中的令牌,则会得到相同的令牌,但当我保留它时,哈希值是不同的。

  • 提供请求数据中的_token与将令牌作为X-CSRF-TOKEN头转发有何不同?如果我在未加密的情况下看到它们,Laravel如何验证它们?它们会在请求后加密吗?


  • 1
    这里有很多不同的问题,这与本网站的格式不太适合:虽然一个答案可能涵盖所有问题,但很容易出现多个答案分别涵盖不同方面,或者页面变成讨论和修改的混乱。如果您能将问题集中一下,并在必要时提出多个问题,那会更好。 - IMSoP
    也许这个答案可以帮助你为 CSRF 的内部逻辑 https://dev59.com/WGAh5IYBdhLWcg3wDfoW#51673924 - Paresh Barad
    2个回答

    1
    在代码的哪个部分触发了令牌的创建?在查看帮助程序文件后。
    /vendor/laravel/framework/src/Illuminate/Foundation/helpers.php
    
    csrf_token()助手方法的定义,调用token方法。
    /vendor/laravel/framework/src/Illuminate/Session/Store.php
    

    如果您检查调用regenerateToken()start()函数,如果_token未设置,则会将一个随机的40个字符的字符串保存到会话中,并使用_token作为键。

    /**
     * Regenerate the CSRF token value.
     *
     * @return void
     */
    public function regenerateToken()
    {
        $this->put('_token', Str::random(40));
    }
    
    1. 创建后令牌存储在哪里,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 将保持不变。

    0
    在我的情况下,从.env文件中删除APP_URL=http://localhost解决了CSRF令牌的问题。我不会为本地开发配置固定值的APP_URL,因为我总是通过浏览器使用不同的主机名和端口。

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接