我的一些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设置吗?我真的很奇怪,这些似乎正在掏出已被覆盖的旧数据。
答案 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'));