【问题标题】:Laravel session gets suddenly destroyedLaravel 会话突然被破坏
【发布时间】:2014-07-02 10:00:13
【问题描述】:

我有一个处理体育赛事注册的多页表单。我们有很多用户(约占所有用户的 15%,与平台/浏览器无关)遇到以下错误:

表单包含以下页面:

  1. 开始
  2. 详情
  3. 团队
  4. 批次
  5. 商品
  6. 调查
  7. 完成

在每一页上,我们检查会话是否包含前一页的数据。如果没有,我们将他重定向回来。

遇到的问题是第 4 步输入数据后 15% 组被重定向回来。

这可能意味着会话/数据在第 4 步的存储功能中被损坏,但我不知道如何/为什么/在哪里。但如果这是问题所在,那么只有 15% 的用户会遇到问题是没有意义的。此外,经过数小时的尝试,我们无法重现此错误。

我知道会话被完全刷新/销毁,因为用户被级联返回:showBatchPage 将用户恢复为 showClassPage,showClassPage 恢复为 showMembersPage,showMembersPage 恢复为 showStartPage 等。我们还会记录这些恢复。

我的代码如下所示:

<?php

public function saveClassPage($slug)
{
    $rules = [];
    $messages = [];
    $memberClasses = [];    

    // prepare solo error messages    
    foreach (Session::get('entry.members') as $id => $member)
    {
        if (!isset($member['group'])) {
            $rules["class.{$id}"] = 'required';
            $messages["class.{$id}.required"] = "Please select a class for member {$member['firstname']} {$member['lastname']}";
        }
    }

    // prepare team error messages
    foreach (Session::get('entry.groups', []) as $id => $group)
    {
        $rules["group.{$id}"] = 'required';
        $messages["group.{$id}.required"] = "Please select a class for group {$group['name']}";
    }

    $validator = Validator::make(Input::all(), $rules, $messages);

    // loop trough solo members and set class
    foreach (Input::get('class', []) as $i => $class)
    {
        Session::put("entry.members.{$i}.class", $class);

        // if there is only one class in the batch, assign it
        $memberClasses[$i] = ClassModel::find($class);
        if ($memberClasses[$i]->batches()->count() < 2) {
            Session::put("entry.members.{$i}.batch", $memberClasses[$i]->batches()->first()->id);
        }
    }

    // loop trough teams and set class
    foreach (Input::get('group', []) as $i => $class)
    {
        foreach (Session::get("entry.groups.{$i}.members", []) as $id)
        {
            Session::put("entry.members.{$id}.class", $class);

            // if there is only one class in the batch, assign it
            $memberClasses[$id] = ClassModel::find($class);
            if ($memberClasses[$id]->batches()->count() < 2) {
                Session::put("entry.members.{$i}.batch", $memberClasses[$id]->batches()->first()->id);
            }
        }
        Session::put("entry.groups.{$i}.class", $class);
    }

    $allClassesAreEmpty = true;
    foreach ($memberClasses as $class)
    {
        if ($class->batches()->count() > 1) {
            $allClassesAreEmpty = false;
            break;
        }
    }

    if ($validator->passes()) {
        // skip batch page if there is only one batch
        if ($allClassesAreEmpty) {
            return Redirect::action('EventEntryController@showExtrasPage', array('slug' => $slug));
        } else {
            return Redirect::action('EventEntryController@showBatchPage', array('slug' => $slug));
        }
    }

    return Redirect::action('EventEntryController@showClassPage', array('slug' => $slug))->withErrors($validator);
}

public function showBatchPage($slug)
{
    $firstMember = head( Session::get('entry.members', []) );

    if (!isset($firstMember['class'])) {
        Log::info('showBatchPage@revertToClass');

        return Redirect::action('EventEntryController@showClassPage', array('slug' => $slug));
    }

    // other stuff (preparing view data etc.)

    return View::make('entry/batch', $viewData);
}

我的应用程序/config/session.php

<?php

return array(

    /*
    |--------------------------------------------------------------------------
    | Default Session Driver
    |--------------------------------------------------------------------------
    |
    | This option controls the default session "driver" that will be used on
    | requests. By default, we will use the lightweight native driver but
    | you may specify any of the other wonderful drivers provided here.
    |
    | Supported: "file", "cookie", "database", "apc",
    |            "memcached", "redis", "array"
    |
    */

    'driver' => 'file',

    /*
    |--------------------------------------------------------------------------
    | Session Lifetime
    |--------------------------------------------------------------------------
    |
    | Here you may specify the number of minutes that you wish the session
    | to be allowed to remain idle before it expires. If you want them
    | to immediately expire on the browser closing, set that option.
    |
    */

    'lifetime' => 120,

    'expire_on_close' => false,

    /*
    |--------------------------------------------------------------------------
    | Session File Location
    |--------------------------------------------------------------------------
    |
    | When using the native session driver, we need a location where session
    | files may be stored. A default has been set for you but a different
    | location may be specified. This is only needed for file sessions.
    |
    */

    'files' => storage_path().'/sessions',

    /*
    |--------------------------------------------------------------------------
    | Session Database Connection
    |--------------------------------------------------------------------------
    |
    | When using the "database" or "redis" session drivers, you may specify a
    | connection that should be used to manage these sessions. This should
    | correspond to a connection in your database configuration options.
    |
    */

    'connection' => null,

    /*
    |--------------------------------------------------------------------------
    | Session Database Table
    |--------------------------------------------------------------------------
    |
    | When using the "database" session driver, you may specify the table we
    | should use to manage the sessions. Of course, a sensible default is
    | provided for you; however, you are free to change this as needed.
    |
    */

    'table' => 'sessions',

    /*
    |--------------------------------------------------------------------------
    | Session Sweeping Lottery
    |--------------------------------------------------------------------------
    |
    | Some session drivers must manually sweep their storage location to get
    | rid of old sessions from storage. Here are the chances that it will
    | happen on a given request. By default, the odds are 2 out of 100.
    |
    */

    'lottery' => array(2, 100),

    /*
    |--------------------------------------------------------------------------
    | Session Cookie Name
    |--------------------------------------------------------------------------
    |
    | Here you may change the name of the cookie used to identify a session
    | instance by ID. The name specified here will get used every time a
    | new session cookie is created by the framework for every driver.
    |
    */

    'cookie' => 'laravel_session',

    /*
    |--------------------------------------------------------------------------
    | Session Cookie Path
    |--------------------------------------------------------------------------
    |
    | The session cookie path determines the path for which the cookie will
    | be regarded as available. Typically, this will be the root path of
    | your application but you are free to change this when necessary.
    |
    */

    'path' => '/',

    /*
    |--------------------------------------------------------------------------
    | Session Cookie Domain
    |--------------------------------------------------------------------------
    |
    | Here you may change the domain of the cookie used to identify a session
    | in your application. This will determine which domains the cookie is
    | available to in your application. A sensible default has been set.
    |
    */

    'domain' => null,

    /*
    |--------------------------------------------------------------------------
    | HTTPS Only Cookies
    |--------------------------------------------------------------------------
    |
    | By setting this option to true, session cookies will only be sent back
    | to the server if the browser has a HTTPS connection. This will keep
    | the cookie from being sent to you if it can not be done securely.
    |
    */

    'secure' => false,

);

【问题讨论】:

  • 你能发布你所有的 app/config/session.php 代码吗?
  • 您是否尝试过切换会话类型?也许是数据库,或者安装 memcache?
  • 不,还没有。你认为这有什么关系?由于问题发生在同一个位置,而且并非总是如此(如果我完全复制受影响的用户操作,我完全没有问题),对我来说,它不希望成为会话提供者的问题。
  • 它是关于排除事情的。如果问题发生在数据库会话中 - 那么您知道它不是您的文件会话。但目前你还不确定——这可能是最简单的改变选择。
  • 哦 - 还有一件事 - 将你的 cookie 更改为不带下划线的东西 - 一些较旧的 IE 浏览器不喜欢带下划线的 cookie。

标签: php session laravel laravel-4


【解决方案1】:

假设您正在使用本地盒子(Dev),以避免使用相同的默认 Session Cookie Name 和相同的 domain 与其他 Laravel 应用程序混淆:

  1. 清除所有与您的 Laravel 应用程序使用的域相关的 browser cookies 以进行故障排除。
  2. 将您的Session Cookie Name 更改为更独特的(如果需要,不要下划线)。

如果您使用默认会话驱动程序file,请确保您对文件夹app/storage 具有写入权限。

【讨论】:

  • 已经试过了,但是没有用。将 cookie 名称更改为唯一名称,后来更改为 db 驱动程序以排除文件系统错误。仍然没有发现问题,并且仍然无法重现它。
猜你喜欢
  • 2016-04-28
  • 2019-07-01
  • 2019-02-23
  • 1970-01-01
  • 2016-06-15
  • 2019-04-25
  • 2013-10-31
  • 2012-07-24
  • 2011-09-19
相关资源
最近更新 更多