在laravel中解决令牌不匹配错误的正确方法是什么?

时间:2017-07-20 18:54:47

标签: laravel token csrf csrf-protection

因为我已经将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. 列出" XSRF-TOKEN" $excepted \MiddleWare\EncryptCookies.php下的ca.company.project可行选项,或者您可以建议更好的解决方案吗? (这使我们回到问题#3)
  5. 我很抱歉这么多问题,并提前致谢!

    修改

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

3 个答案:

答案 0 :(得分:2)

The function that checks the token尝试使用密钥_token在请求 plain 中找到(1),如果找不到,则将尝试使用密钥X-CSRF-TOKEN查看(2)请求标头。要匹配的令牌存储在会话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中,即   包含在框架生成的每个响应中。您可以使用   用于设置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中将$ XSL下的“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);
    }

答案 1 :(得分:0)

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

sudo rm -rf storage/framework/sessions/*
sudo php artisan cache:clear
sudo php artisan clear-compiled
sudo composer dump-autoload
所有你解决类似问题的人可能已经遇到过数百次了。我经常发现的另一个建议是更改存储文件夹的权限,这可能有助于解决类似的问题!

答案 2 :(得分:0)

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

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

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

php artisan config:clear