PHP会话';页面重新加载之间的数据不一致-尽管会话ID相同

PHP会话';页面重新加载之间的数据不一致-尽管会话ID相同,php,session,web,Php,Session,Web,我的一些PHP代码有一个非常奇怪的问题。我已打开错误报告,但也没有出现任何问题 基本上,我有一个表单可以将数据推送到$\u SESSION[]。代码是: <?php session_start(); $_SESSION['contact']['name'] = $_GET['name']; $_SESSION['contact']['email'] = $_GET['email']; $_SESSION['contact']['question'] = $_GET['question']

我的一些PHP代码有一个非常奇怪的问题。我已打开错误报告,但也没有出现任何问题

基本上,我有一个表单可以将数据推送到$\u SESSION[]。代码是:

<?php 
session_start();
$_SESSION['contact']['name'] = $_GET['name'];
$_SESSION['contact']['email'] = $_GET['email'];
$_SESSION['contact']['question'] = $_GET['question'];

session_write_close();
header('Location: confirm.php');
exit;
?>

这是正在工作的。但是,confirm.php完全随机地接收或不接收此数据。如果我刷新多次,我有时会得到数据,有时不会

这是确认代码:

<?php
ini_set('display_errors', 'on');
error_reporting(-1);

session_start();

print "SeshID:" . session_id() . "<br>";
print "CookieID:" . $_COOKIE['PHPSESSID'] . "<br>";
print "Status" . session_status() . "<br>";
print "Loc" . session_save_path() . "<br>";
print "Cookie";
print_r(session_get_cookie_params());
print "<br>Data:<br>";

print_r($_SESSION);
?>

同样,没有错误。看起来没有什么明显的错误

奇怪的是,有时候当我刷新确认页面时,我会得到一个空的“Array()”。有时我会得到“数组([contact]=>数组([question]=>test[name]=>[email]=>test@test.com))“似乎没有理由

在执行此操作之间,我没有运行任何其他脚本-只有上面检查会话内容(确认)的脚本需要重新运行,只有数据以某种方式更改。我运行了几次表单,然后检查脚本,结果完全不一致会话和cookie ID永远不会更改,并且始终相同


我是否缺少一些PHP设置?对我来说,这真的很奇怪,它们似乎正在提取已被覆盖的旧数据。

刷新页面后,会话仍然经过身份验证,但我们丢失了使用指令手动添加的内容 试试这个 (此.set('session.X','Y'))

已解决! 我会为有同样问题的人发布我自己的答案。感谢在评论中帮助我发现这一点的人

问题 问题是服务器使用集群或分发网络mine Azure来服务PHP文件

第一个调用将会话数据写入机器1,然后确认从没有正确信息的机器2读取。在集群中,/tmp通常不镜像,而会话数据存储在集群中。请与您的群集管理员讨论此问题巴特·弗里德里克斯

似乎表单正在发送,会话变量存储在服务器1上,但提取会话数据的页面是服务器2、服务器3,有时是服务器1,因此出现了看到以前提交的数据和偶尔更正数据的奇怪行为

修复 这里有两种可能的修复方法。一:

未在所有服务器上镜像会话存储目录 在这种情况下,通过更改php.ini中的“session.save_path”或使用

session_save_path(dirname(__FILE__). '/sessions/');
在调用session_start()
之前,在受影响文件的顶部(这是我们站点中唯一使用会话的部分,因此这是一个好的/不好的修复)

这里的要点是将其更改为一个目录,确保在集群中的每台服务器上都进行镜像

正在以另一种不镜像的方式保存会话 在我的实际案例中,我发现我的会话处理程序就是问题所在。利用

phpinfo();
我发现我的session.save_处理程序是“wincache”,这是一个加速PHP的插件。其中一种方法似乎是通过使用共享内存或其他东西来加速会话数据的加载

无论哪种方式,这都不适合我的设置,我通过简单地更改变量以使用默认值“files”来修复它

同样,最好的方法是使用php.ini并将session.save\u处理程序设置为“files”,但我没有访问该文件的权限,因此,在session\u start()之前,我只在两个文件的头中调用了

ini_set("session.save_handler", "files");
我不推荐这个,因为你知道,当一个新的开发人员进来时,它会突然出现,并在后面咬你一口,而你却忘记了——最好更改你的.ini

总之,就是这样

谢谢大家的帮助

在一边
许多服务器解决方案(如Azure)实际上都专门提供了自己的插件和会话处理程序来应对这种情况。如果可能的话,你当然应该使用它们

我会尝试取出session\u write\u close()并再试一次。您确定每次刷新confirm.php页面时,$\u GET参数仍在url中吗?如果它们丢失,$\u会话变量将不会被写入,原因很明显是服务器是集群的一部分还是在负载平衡器后面?当数据丢失时,它是保持丢失还是来去自如?@jeffery_the_wind,done。不过,问题仍然存在。@Tobywilks您的管理员会知道,但您可以相当确定存储PHP脚本的目录已镜像。您可以在那里创建一个子目录“会话信息”。确保它们可供Web服务器用户写入。关于WinCache:您完全正确:如果您处于负载平衡环境中,并且有多个工作进程,并且没有启用客户端关联,那么您必须使用由所有工作进程共享的会话缓存机制。WinCache的会话缓存仅在同一工作进程上的php cgi进程之间共享。您可以使用
session.save\u handler=files
,并将
session.save\u路径
指向共享文件夹。或者您可以使用Redis或memcached作为共享缓存。