我遇到了一个$_SESSION
问题,而$_SESSION
正在随机丢失数据。
我有一个包含不同页面的表单,用户有特定的时间浏览所有页面。
所以我在第一页设置了一个会话变量,并在其他页面上进行检查。
start.php
<?php
session_start();
//Set Variable for Starting application
if (!isset($_SESSION['STARTED'])){
$_SESSION['STARTED'] = time();
}
app_init.php
<?php
session_start();
if ((!isset($_SESSION['STARTED'])) || (time() - $_SESSION['STARTED'] > MAX_TIMELIMIT)) {
echo '<!-- st: '.$_SESSION['STARTED'].'-->';
// Started Variable is not set or timelimit is over.
session_destroy(); // destroy session data in storage
session_unset(); // unset $_SESSION variable for the runtime
showTimeout('0'); // show timeout
}
之后页面的开始:
<?php
// get basic settings for applications
require_once (MODEL_PATH.'/app_init.php');
整个系统在本地安装、Developmentserver和Testserver上运行良好。在Productionserver上,我在不同的时间得到一个超时。它从30秒到10分钟不等。CCD_ 3为20分钟。在这种情况下,$_SESSION['STARTED']
总是空的。在其他环境中,即使超时在20分钟后出现,它也会被正确设置。
附加信息:
- 无论我是尝试访问下一页,还是只是重新加载实际页面,我总是会超时
- 我已经在任何环境中检查了
php.ini
->session.save_path
设置正确,session.cookie_lifetime
为0,session.gc_maxlifetime
为1440 - 磁盘空间良好(>22 GB可用空间(
- 每个文件都在同一台服务器上,都有相同的url(除了指定表单步骤的最后一部分。看起来像这样:
host/some/path/calc->host/some/path/form->host/ssome/path/summary->host/som/path/send - 会话在计算页面上设置,超时可能发生在每个页面上(计算、表单、摘要(
- 我从生产服务器上获得了php.ini,并将其放入本地工作区。在更改了一些路径(扩展路径、session.save_path、tmp路径(后,它在我的本地安装中运行得很好
- 协议是一个所有页面都相同的
- 重新创建会话(通过
$tmp
和session_destroy()
,session_create()
(没有帮助 - 单一前端,没有负载均衡器(只是一个apache(
- 会话文件以某种方式被删除
在添加了一些输出并重新测试后,我得到了以下内容:
- 我加载页面(第一步(
- 我从表格到任何步骤(计算/表格/摘要(
加载页面时,
$_SESSION
为array ( 'STARTED' => 1338298801, 'S_SID_' => '41554681145546', 'S_LC_' => 'de', 'version_testing' => 1, )
我每30秒重新加载一次
至少在3分钟后(也可能是30秒(,我得到了超时,
$_SESSION
是:array ( )
如果我在第一页上尝试,我会在
$_SESSION
中获得一个新值,因为sessiondata是空的,并且自动设置为新值。请记住:在测试/开发环境中,sessiondata仍然存在,即使超时发生在20分钟后。
更改session.save_path似乎首先起作用(会话至少持续24分钟(。但一个小时后,仍然是同样的问题。没有一节课的时间超过4分钟。
发现问题(但尚未解决(
今天我访问了生产服务器,我发现包含会话数据的文件夹在3-5分钟后就会被清理干净。没有文件的时间戳超过3分钟。如前所述,PHP设置正确(GC生存期(,我没有发现任何windows作业,也没有发现类似的删除这些文件的操作。由于PHP.ini设置正确,我将尝试通过数据库处理会话。
感谢的帮助
在这种特定情况下起作用的是:
另一个网站位于同一台服务器上,但位于不同的虚拟主机中。这个网站使用了一个"init.php",每次请求都会调用它。它包含一行,将gc_maxlifetime设置为0,然后启动一个会话。因此,在某个请求下,第二个网站随机清除了所有sessiondata。
在测试和开发中,这不是问题,因为这两个环境没有那么多使用。。。
当PHP网站托管在带有负载均衡器的多个前端时,这是我多次看到的常见行为。默认情况下,PHP将会话存储在文件系统上,根据您所在的位置,您启动了一个或另一个会话。
简单的解决方案是将会话存储到数据库中,即使我对负载均衡器的看法是错误的,你也应该尝试直接读取文件系统上的会话数据,检查到底发生了什么(PHP正在删除数据吗?数据是否仍在这里,但生成了另一个会话令牌?等等…(。
乍一看(没有更多信息(,您的会话似乎是在实际应该启动的时间之前启动的。这无疑会造成这个问题。如果这可能是问题所在,试试这个。
$tmp = $_SESSION;
session_destroy();
session_start();
$_SESSION = $tmp;
$_SESSION['started'] = time();
此外,如果你正在访问子域或类似的区域,你的会话将不存在。它只存在于设置时所在的确切域中。
多提供一些信息可能也会有所帮助。存在问题的页面的URL。在页面上添加一些var_dump($_SESSION)
,并在逐步完成时查看它的输出。当你注意到一个变化时,弄清楚它在哪里以及为什么变化。