PHP会话的数据在页面重新加载之间不一致 - 但会话ID是相同的

时间:2016-07-05 06:50:23

标签: php session web

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

基本上我有一个将数据推送到$ _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;
?>

这是正常工作。但是,完全在 random ,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()”。有时我会得到“Array([contact] =&gt;数组([问题] =&gt;测试[名称] =&gt; [电子邮件] =&gt; test@test.com))”因为看似没有理由......

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

我缺少一些PHP设置吗?我真的很奇怪,这些似乎正在掏出已被覆盖的数据。

2 个答案:

答案 0 :(得分:3)

解决!

我会为遇到同样问题的人发布自己的答案。感谢帮助我发现这一点的人们的帮助!

问题

问题是服务器正在使用群集或分发网络,我的 Azure 来提供PHP文件。

  

第一次调用将会话数据写入机器1,然后确认从机器2读取,机器2没有正确的信息。在群集中,/ tmp通常不会被镜像,这就是会话数据的存储位置。与您的群集管理员讨论此事。 - Bart Friederichs

似乎正在发送表单并将会话变量存储在服务器1上,但是拉取会话数据的页面是服务器2,服务器3,有时是服务器1 - 因此奇怪的行为查看先前提交的内容并偶尔更正数据。

修复

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

会话存储目录未在所有服务器上进行镜像

在这种情况下,通过更改&#34; session.save_path&#34;来更改会话目录。在你的php.ini或使用

session_save_path(dirname(__FILE__). '/sessions/');
在您调用session_start()之前,

位于受影响文件的顶部(这是我们网站中仅使用会话的部分,因此这是为了进行良好/肮脏的修复)。

这里的要点是将其更改为一个目录,该目录肯定会在群集中的每个服务器上进行镜像。

会话以另一种未镜像的方式保存

在我的实际案例中,我发现我的会话处理程序是问题所在。使用

phpinfo();

我发现我的session.save_handler是&#34; wincache&#34;,这是一个加速PHP的插件。其中一种方法是使用共享内存或其他方式来加速会话数据的加载。

无论哪种方式,这都不适合我的设置,我只需更改变量即可使用默认设置来修复它:&#39;文件&#39;。

同样,最好的方法是使用 php.ini 并将session.save_handler设置为&#34;文件&#34;但我无法访问该文件,因此,我只是在session_start()之前的两个文件的标题中使用了一个电话。

ini_set("session.save_handler", "files");

我不会推荐这个,因为你知道它会在后面出现并且在新的开发人员进来时让你忘记 - 最好更改你的的.ini

无论如何,就是这样。

感谢大家的帮助!

除了

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

答案 1 :(得分:-4)

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