【问题标题】:What is the right way to resolve token mismatch error in laravel?解决 laravel 中令牌不匹配错误的正确方法是什么?
【发布时间】:2017-12-26 15:29:12
【问题描述】:

自从我将 laravel 更新到 5.4 后,我不断得到:

TokenMismatchException in VerifyCsrfToken.php line 68

抛出异常。经过一些挖掘和阅读大量帖子和 github 问题后,我发现我的令牌不匹配:)。关键是我的 laravel 应用程序设置了令牌“XSRF-TOKEN”的加密版本,而不是其普通 (X-CSRF-TOKEN) 对应项,并且助手 csrf_token() 吐出普通令牌,因此令牌不匹配。令人困惑的是,为什么当我得到 XSRF-TOKEN(缺少 X-)时文档会提到 X-XSRF-TOKEN?所以问题是:

  1. 缺少的“X-”有什么含义吗?
  2. 如何将令牌的加密版本更改为普通版本? (不管第 3 个问题)
  3. 我什至应该尝试从加密的令牌中制作一个普通令牌,还是最好加密csrf_token()? (这是否重要,因为连接是加密的?)
  4. \MiddleWare\EncryptCookies.php 中的$excepted 下列出“XSRF-TOKEN”是一个可行的选项,或者您能建议一个更好的解决方案吗? (这让我们回到了问题 #3)

很抱歉有这么多问题,提前感谢!

编辑

在多次重读我的问题后,我得出的结论是它们不够清楚并且不符合标题。我的问题是令牌不匹配,我认为消除我的疑虑会导致我找到解决方案,我感谢@ThomasMoors 的耐心和帮助。我会接受他的回答,虽然我用不同的方式解决了我的问题,但正是他的帮助让我找到了解决方案!我还发布了我自己的答案,其中描述了我如何解决我的问题以帮助其他有类似问题的人!

【问题讨论】:

  • @ThomasMoors 您能否更准确地了解我的服务器如何知道我的令牌是否是我的令牌?私人秘密会起作用吗?您能否建议一个修补选项以激活普通令牌?谢谢

标签: laravel token csrf csrf-protection


【解决方案1】:

The function that checks the token 尝试在 plain 请求中找到它 (1) 使用密钥 _token,如果找不到它,它将尝试查找在 (2) 内带有键 X-CSRF-TOKEN 的请求标头。要匹配的令牌存储在会话中,where the session lives depends on your config

    /**
     * Determine if the session and input CSRF tokens match.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return bool
     */
    protected function tokensMatch($request)
    {
        $token = $request->input('_token') ?: $request->header('X-CSRF-TOKEN');
        if ( ! $token && $header = $request->header('X-XSRF-TOKEN'))
        {
            $token = $this->encrypter->decrypt($header);
        }
        return StringUtils::equals($request->session()->token(), $token);
    }

缺少的“X-”有什么意义吗?

A:Laravel 将当前的 CSRF 令牌存储在一个 XSRF-TOKEN cookie 中,该 cookie 是 包含在框架生成的每个响应中。您可以使用 用于设置 X-XSRF-TOKEN 请求标头的 cookie 值。

此 cookie 主要是为了方便而发送的,因为某些 JavaScript 框架和库,如 Angular 和 Axios,会自动放置 它在 X-XSRF-TOKEN 标头中的值。

如何将令牌的加密版本更改为普通版本? (不管问题#3)

A:在上面的代码中(来自 github)\Illuminate\Contracts\Encryption\Encrypter 有一个名为 decrypt() 的函数来执行此操作

我是否应该尝试从加密的令牌中制作一个普通令牌,还是最好改为加密 csrf_token()? (这是否重要,因为连接是加密的?)

A:没关系,因为令牌里面没有数据,它只是来自您的站点的合法请求的标识符,而不是来自另一个域的一些 ajax/xhr 调用。阅读更多https://en.wikipedia.org/wiki/Cross-site_request_forgery

在 \MiddleWare\EncryptCookies.php 的 $excepted 下列出“XSRF-TOKEN”是一个可行的选择,还是您能提出更好的解决方案? (这让我们回到了问题 #3)

A:令牌在任何时候都没有理由在 cookie 中,不是吗?

更新

似乎从 5.0 到 5.4 确实在上面的函数中有 has changed。现在看起来像这样:

 protected function tokensMatch($request)
    {
        $token = $this->getTokenFromRequest($request);
        return is_string($request->session()->token()) &&
               is_string($token) &&
               hash_equals($request->session()->token(), $token);
    }

【讨论】:

  • 在用户会话到期之前,令牌不应该在 cookie 中吗?我仍然不明白如何让我的中间件通过测试?我真的应该修补它(中间件)并调用decrypt 方法(听起来对我来说不是一个正确的解决方案)吗?到目前为止,我是否没有错过一些配置选项来设置普通会话 cookie,或者我应该在渲染视图之前手动设置它吗?
  • Cookies 识别会话(除非您使用 cookie 驱动程序),但它的值存储在某处取决于 the driver
  • 哦,我想我误解了 cookie、会话和令牌部分,我熟悉会话工作流程(至少我认为我是 :))。我将会话 cookie 与令牌混合在一起,您可能的意思是令牌不必存储在 cookie 中,因为它可以与请求标头一起发送(如在 AJAX reuest 中),对吗?在那种情况下,我想稍微澄清一下我的问题,我实际上是指它的加密,如果我在$excepted 下列出令牌名称,它将不会被加密并且我不再得到TokenMismatchException,我想知道如果这是解决我的问题的正确方法?
  • 不需要加密您的 csrf-token:它不包含重要数据:它只是告诉“此请求来自您的网站,not a fake / xhr / ajax call from another website.跨度>
  • 谢谢,不必加密的部分我现在很清楚,问题是,不是我开始加密它的。这是我更新后的默认行为,我很挣扎,因为我的应用程序不是一些干净、新鲜的 laravel 安装,而是一个代码库,现在我必须找到一种方法来摆脱这个异常而不产生安全漏洞。现在,在 laravel 中,将加密的 cookie 变成未加密的 cookie 的正确方法(最佳实践)是什么(因为至少目前这是我摆脱异常的唯一方法)?
【解决方案2】:

虽然我无法确定问题的根源(由于缺乏框架经验),但我终于可以解决我的问题了。到目前为止我错过的是一些 middleware classes 被移动到 app/Http/Kernel.php 文件中的不同中间件组(我的问题可能出现因为 它们的加载顺序发生了变化,或者可能是因为其中一些根本没有加载?)。我很确定,这是我的问题的原因,因为我不断地重新加载我的页面以及清除缓存,就像 github 上建议的那样,这是由 jeremykenedy 建议的。建议是调用以下命令:

sudo rm -rf storage/framework/sessions/*
sudo php artisan cache:clear
sudo php artisan clear-compiled
sudo composer dump-autoload

你们所有处理类似问题的人可能已经遇到过数百次了。我经常发现的另一个建议是更改存储文件夹的权限,这可能有助于你们中的一些人解决类似的问题!

【讨论】:

    【解决方案3】:

    我发现了一个关于令牌不匹配异常的有趣的事情。我在 AppServiceProvider 中将我的日期时间伪造为:

    /**
    * Bootstrap any application services.
    *
    * @return void
    */
    public function boot()
    {
        Carbon::setTestNow('2000-07-05 4:00 pm');
    }
    

    在那之后我无法登录到我的 laravel 应用程序。否则只需一个命令即可解决令牌不匹配异常。

    php artisan config:clear
    

    【讨论】:

      猜你喜欢
      • 2020-11-08
      • 2021-10-22
      • 2022-11-15
      • 2016-06-21
      • 1970-01-01
      • 2022-08-19
      • 2017-06-06
      • 2020-05-10
      • 2016-11-25
      相关资源
      最近更新 更多