【问题标题】:Laravel TokenMismatchException database sessionLaravel TokenMismatchException 数据库会话
【发布时间】:2017-07-06 15:30:51
【问题描述】:

从文件切换到数据库会话时,我的 $request->input(_token) 与 $request->session()->toke() 不匹配。

这会导致 CSRF TokenMismatchException。当从数据库切换回文件会话驱动程序时,不会发生不匹配。

有谁知道我为什么会出现这种不匹配以及如何解决它? :) 我做了什么:


使用 Laravel 5.0
PHP 5.6.30

php artisan session:table : 创建 Laravel 会话表 作曲家转储自动加载 php工匠配置:清除 php arisan 配置:缓存

我的 session.php 配置如下所示:

return [

    'driver' => 'database',
    'lifetime' => 120,
    'expire_on_close' => false,
    'encrypt' => false,
    'files' => storage_path().'/framework/sessions',
    'connection' => null,
    'table' => 'laravel_session',
    'lottery' => [2, 100],
    'cookie' => 'laravel_session',
    'path' => '/',
    'domain' => null,
    'secure' => false,

];

VerifyCsrfToken Illuminate\Foundation\Middleware

protected function tokensMatch($request)
{
    $tok =  $request->input('_token') ; //4ExGXl9mRM75d7brfQhgIWcQzsSVjnUHDoDcKJxp
    $tokhead  = $request->header('X-CSRF-TOKEN'); 
    $sessToken = $request->session()->token();//57DLb3uTs8brVPKpBxor14Hg0ZvQPpYW3flktP86

    $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);

切换到数据库sesseio驱动后,数据库表填充数据:

SELECT id, payload, last_activity, user_id FROM kartserver_2.laravel_session;

d33d5782e1eed56771baa56f9410a24b9e628ff6    YToxNzp7czo2OiJfdG9rZW4iO3M6NDA6Ikh6dUc4WG1PUDFZalRHY0QwcW5QZzlFSGRUSkJ3ZmVOUkVjM0RJVk0iO3M6NToiZmxhc2giO2E6Mjp7czozOiJvbGQiO2E6MDp7fXM6MzoibmV3IjthOjA6e319czoyMDoicGFzc3dvcmRSZXF1aXJlbWVudHMiO086NDE6Ikhhd2tTb2Z0d2FyZVxTZWN1cml0eVxQYXNzd29yZFJlcXVpcmVtZW...   1487315670  1862

我在 html 中生成 csrf_tokens

<input type="hidden" name="_token" id="_token" value="{!! csrf_token() !!}">

【问题讨论】:

  • 你在使用 php artisan serve 吗?
  • 会话令牌!= csrf 令牌
  • 是的,没错。会话令牌与 csrf-token 不同。但为什么? :) 以及如何解决它
  • 因为它们根本不是同一种东西,它们的用途不同。
  • 这很奇怪。因为当我切换回文件会话时,它们是相同的并且不会抛出异常

标签: php html laravel session frameworks


【解决方案1】:

如果您使用的是 Laravel 5.4* 并且碰巧遇到了这个问题,那么您需要这样做

1- 更新您的 .env 文件

# file = .env in your project root

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=testdb
DB_USERNAME=db_user
DB_PASSWORD=secret_pass

SESSION_DRIVER=database

请注意此处的 DB_CONNECTION 设置,您将在下一步中使用它。

2- 更新 config/session.php 文件 连接参数应该包含您在 .env 文件中用于 DB_CONNECTION 的字符串

# file = config/session.php

'driver' => env('SESSION_DRIVER', 'database'),
'connection' => 'mysql', // this is from DB_CONNECTION in .env file 

3- 生成会话表

php artisan session:table
// run the migration !!! very very important
php artisan migrate

4- 如果出于某种原因您决定手动创建表而不使用迁移,请使用此 SQL。这是非常重要的一步,一个错误的表会导致各种问题。 主要是不要犯错误,像往常一样手动创建 id 列为 bigint 的表,session 表不同。

如果您想手动创建,您应该运行的会话表 SQL

DROP TABLE IF EXISTS `sessions`;
create table sessions
(
  id varchar(255) not null,
  user_id int(10) unsigned null,
  ip_address varchar(45) null,
  user_agent text null,
  payload text not null,
  last_activity int not null,
  constraint sessions_id_unique
  unique (id)
)

这应该可以解决将db设置为会话保存路径后的令牌不匹配异常。

【讨论】:

  • 非常感谢。它引发了错误的 CSRF_TOKEN 不匹配。这只是数据库表结构:我作为 int 而不是 text 的 Id 字段
  • 这导致我以自己的方式发现错误。您还需要在.env 文件中将SESSION_CONNECTION 设置为数据库连接名称。
【解决方案2】:

他们应该是不同的:)

  • csrf 令牌 是一种防止 csrf 攻击的方法。这是一种攻击形式,如下例所示:

您有一个在访问时触发的GET /pay50dollarToHarry(非常愚蠢的示例)端点。当去诸如 stackoverflow 之类的论坛并发布如下图片时:

<img src="youdomain.com/pay50dollarToHarry />

浏览器将访问该链接以获取图像并转移 50 美元。通过在表单中​​使用 csrf 令牌,这无法从其他页面完成。

  • 会话令牌用于跨您网站的多个页面跟踪用户。

附:请不要更改框架/库中的代码:它们将在更新时被覆盖。这是不好的做法。原函数:

/**
     * Determine if the session and input CSRF tokens match.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return bool
     */
    protected function tokensMatch($request)
    {
        $token = $this->getTokenFromRequest($request);
        return is_string($request->session()->token()) &&
               is_string($token) &&
               hash_equals($request->session()->token(), $token);
    }

【讨论】:

  • 好吧,公平 :) 但我的问题仍然存在。为什么我在 VerifyCsrfToken.php 第 51 行得到 TokenMismatchException:切换到数据库会话时?
  • 如果您在表单中使用默认的 csrf 中间件(未更改)和{{ csrf_field() }} ,它可以保证工作
猜你喜欢
  • 2015-02-24
  • 2015-11-26
  • 1970-01-01
  • 2016-05-23
  • 1970-01-01
  • 2016-12-15
  • 2014-11-27
  • 2015-02-26
  • 2015-10-04
相关资源
最近更新 更多