Laravel 会话突然被破坏
Posted
技术标签:
【中文标题】Laravel 会话突然被破坏【英文标题】:Laravel session gets suddenly destroyed 【发布时间】:2014-07-02 10:00:13 【问题描述】:我有一个处理体育赛事注册的多页表单。我们有很多用户(约占所有用户的 15%,与平台/浏览器无关)遇到以下错误:
表单包含以下页面:
-
开始
详情
团队
类
批次
商品
调查
完成
在每一页上,我们检查会话是否包含前一页的数据。如果没有,我们将他重定向回来。
遇到的问题是第 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。 【参考方案1】:假设您正在使用本地盒子(Dev),以避免使用相同的默认 Session Cookie Name
和相同的 domain
与其他 Laravel 应用程序混淆:
-
清除所有与您的 Laravel 应用程序使用的域相关的
browser cookies
以进行故障排除。
将您的Session Cookie Name
更改为更独特的(如果需要,不要下划线)。
如果您使用默认会话驱动程序file
,请确保您对文件夹app/storage
具有写入权限。
【讨论】:
已经试过了,但是没有用。将 cookie 名称更改为唯一名称,后来更改为 db 驱动程序以排除文件系统错误。仍然没有发现问题,并且仍然无法重现它。以上是关于Laravel 会话突然被破坏的主要内容,如果未能解决你的问题,请参考以下文章