繁体   English   中英

为什么PHP不使用Internet Explorer为特定用户保存会话变量?

[英]Why does PHP not save session variables for specific users with Internet Explorer?

我的网站存在问题,PHP无法使用Internet Explorer为特定用户保存会话变量。 但对于其他一些使用Internet Explorer的用户来说根本没有问题,而使用其他浏览器的用户也没有任何问题。

我创建了以下三个小脚本,以确保不涉及网站中的其他代码:

test.php的:

<?php
session_start();

function logMsg($text) {
    $filename = dirname(__FILE__) . "/test.log";
    $fh = fopen($filename, "a") or die("Could not open log file.");
    fwrite($fh, date("d-m-Y, H:i")." - $text\n") or die("Could not write file!");
    fclose($fh);
}

ob_start();
var_dump(session_id(), $_SESSION, $_SERVER, $_REQUEST);
$content = ob_get_clean();

logMsg("test.php");
logMsg($content);

$_SESSION['test'] = array('test' => 'lalala');
$_SESSION['count'] = 1;
?>
<a href="test2.php">Next</a>

test2.php:

<?php
session_start();

function logMsg($text) {
    $filename = dirname(__FILE__) . "/test.log";
    $fh = fopen($filename, "a") or die("Could not open log file.");
    fwrite($fh, date("d-m-Y, H:i")." - $text\n") or die("Could not write file!");
    fclose($fh);
}

ob_start();
var_dump(session_id(), $_SESSION, $_SERVER, $_REQUEST);
$content = ob_get_clean();

logMsg("test2.php");
logMsg($content);

$_SESSION['count']++;
?>
<a href="test3.php">Next</a>

test3.php:

<?php
session_start();

function logMsg($text) {
    $filename = dirname(__FILE__) . "/test.log";
    $fh = fopen($filename, "a") or die("Could not open log file.");
    fwrite($fh, date("d-m-Y, H:i")." - $text\n") or die("Could not write file!");
    fclose($fh);
}

ob_start();
var_dump(session_id(), $_SESSION, $_SERVER, $_REQUEST);
$content = ob_get_clean();

logMsg("test3.php");
logMsg($content);

var_dump($_SESSION)的预期输出类似于:

array(0) {
}

array(2) {
    ["test"] => array(1) {
        ["test"] => string(6) "lalala"
    },
    ["count"] => int(1)
}

array(2) {
    ["test"] => array(1) {
        ["test"] => string(6) "lalala"
    },
    ["count"] => int(2)
}

但是,有问题的用户的输出如下:

array(0) {
}

array(0) {
}

array(1) {
    ["count"] => int(1)
}

这意味着不会为这些用户存储会话变量。 但是,有问题的用户的会话ID对于所有3个测试页都是相同的。

有人知道这可能是什么吗? 据我所知,有问题的代码工作了好几年,问题在上个月左右开始显现。

编辑

评论中的问题答案:

  • 我无法在本地计算机上复制问题。
  • 我有IE7和IE9用户的问题报告。 但我不能肯定地说其他版本没有问题,因为它们可能还没有被报道。
  • 有问题的用户的浏览器没有禁用cookie,PHPSESSID cookie被发送到服务器。
  • 机器名称中没有 - 或_( https://stackoverflow.com/a/306601/534109 )。
  • 使用session_regenerate_id()重新生成会话ID不会影响有问题的用户的结果。
  • 有问题的用户的时区和时间设置与服务器上的相同。

编辑2

正如@ n​​l-x在注释中所述,数据存储在第二个请求中。 所以我调整了测试场景并添加了另一个步骤来查看会话是否适用于后续请求。 情况就是这样。 step2.phpstep3.php中设置的会话数据保存在请求之间。

所以现在问题是为什么第一个请求的会话数据丢失而后续请求没有丢失?

我发现有问题的用户都安装了Chrome Frame。 我通过在本地计算机上安装Chrome Frame来验证这一点,在这种情况下,我能够复制问题。

问题是由于我们的服务器安装了Suhosin。 启用了以下Suhosin设置:

suhosin.session.cryptua
suhosin.cookie.cryptua

这意味着用户代理字符串也是用户会话标识的一部分。 通常这不是问题,但对于安装了Chrome框架的用户,第一个请求和后续请求之间的用户代理字符串不同。 禁用这些Suhosin设置后,没有更多问题。

我会假定这个,而不是等待具有PHP会话机制特定知识的人:

我主要使用ASP.NET,而Session对象使用cookie来保存跨请求的数据。 如果PHP以相同的方式工作,最明显的结论是会话问题的用户要么禁用cookie,要么使用仅允许列入白名单的域设置cookie的软件。 我会看看能不能找到任何支持这个理论的事实......

从PHP手册( http://www.php.net/manual/en/intro.session.php ):

这可以存储在用户端的cookie中,也可以在URL中传播。

我不能确切地告诉你为什么在第一次请求之后/之后,cookie似乎迷失了。 (这就是我的想法。)为什么第二次请求之后/之后不会丢失。

也许确实是一个缓存问题。 检查开发人员工具,查看网络选项卡中的确切内容。 第一个请求是否带有200 - OK,响应是否包含cookie头? 或者它是否确实被缓存,正如其中一条评论所暗示的那样?

但最终你应该实现正确的会话ID传递 (读取它)。 这适用于不想要或不能处理cookie的人。

基本上它意味着改变:

<a href="test3.php">Next</a>

成:

<a href="test3.php?<?php echo htmlspecialchars(SID); ?>">Next</a>

要么:

启用--enable-trans-sid

现在,当PHP通知会话未通过cookie传递时,它将以不太安全的方式在URL中提供它们。 特别是在这种情况下,您需要session_regenerate_id()

编辑:噢,我想提前提一下,但后来认为不可能。 但第二个想法我仍然会提到它!

Cookie默认为域特定。 如果用户访问http://yourdomain.com (没有www。 ),并且第二个请求转到http://www.yourdomain.com ,则cookie将无法在域更改中存活! 从而影响你的会话。

要解决此问题,请设置会话cookie域,或始终使用相同的域(使用或不使用www。)

首先,您应该验证您的php.ini会话配置,尤其是cookie持续时间。 在您的问题中添加部分。 在客户端上安装Fiddler,该客户端会向您提供错误并生成会话的完整http转储。 这应该可以帮助您轻松追踪问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM