【问题标题】:Why does PHP not save session variables for specific users with Internet Explorer?为什么 PHP 不使用 Internet Explorer 为特定用户保存会话变量?
【发布时间】:2013-05-29 08:18:22
【问题描述】:

我有一个网站的问题,其中 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 个测试页面都是相同的。

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

编辑

cmets中问题的答案:

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

编辑 2

正如@nl-x 在评论中所述,数据存储在第二个请求中。因此,我调整了测试场景并添加了另一个步骤,以查看会话在后续请求中是否有效。情况就是这样。 step2.phpstep3.php 中的会话数据集在请求之间保存。

那么现在的问题是为什么第一个请求的会话数据会丢失,而后续请求的会话数据不会丢失?

【问题讨论】:

  • @GungFoo 怎么样? IE9+ 有很好的标准支持。
  • @HamZaDzCyber​​DeV 大约 30% 的世界,似乎:sitepoint.com/browser-trends-march-2013
  • 特定用户是否禁用了cookies?
  • @nl-x 防止会话劫持?
  • 这似乎是人们抱怨会话无法正常工作的计算机上的缓存问题。可悲的是,修复它超出了您的控制范围,如果您无法复制问题,您能做的最好的事情就是检查他们的 IE 配置以及他们是否在代理后面。如果没有这些信息,您将无法创建修复程序,因为 PHP 端一切正常。

标签: php internet-explorer session


【解决方案1】:

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

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

suhosin.session.cryptua
suhosin.cookie.cryptua

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

【讨论】:

  • 太棒了。这绝对不是我考虑的事情,但这是有道理的(也很高兴知道)。干得好。
【解决方案2】:

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

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

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

这要么存储在用户端的 cookie 中,要么在 网址。

【讨论】:

  • 我确信至少有一位用户存在启用 cookie 的问题。
  • @TiesonT。是的,PHP 的 cookie 的工作方式与您描述的差不多。
  • @Jan-Henk 人物。那太容易成为真正的问题了,不是吗?
  • @Jan-Henk 对类似问题的回答是否会引起任何担忧?:stackoverflow.com/a/306601/534109
  • @TiesonT。我自己已经找到了那一点信息,但是机器名称中没有 - 或 _ 。不过还是谢谢。
【解决方案3】:

我无法准确告诉您为什么在第一次请求时/之后,cookie 似乎丢失了。 (这就是我猜正在发生的事情。)以及为什么在第二个请求之后/之后不会丢失。

也许确实是一个缓存问题。检查开发人员工具,并查看网络选项卡中到底发生了什么。第一个请求是否带有 200 - OK,响应是否包含 cookie 标头?还是如其中一位 cmets 所建议的那样,它确实被缓存了?

但最后你应该真正实现正确的session id passing(阅读它)。这适用于不想要或无法处理 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)。

【讨论】:

  • 我将尝试在测试场景中传递会话 ID,并在收到用户的问题后立即通知您结果。但如果我没记错的话, --enable-trans-sid 选项被禁用了,因为 Google 会在 URL 中使用不同的 PHPSESSID 值多次索引相同的页面。
  • @Jan-Henk 这令人惊讶。我猜谷歌爬虫机器人是启用 cookie 的。因此会阻止 PHP 在 URLS 中使用 SID。
  • 此更改是在大约 5 年前进行的,因此现在可能会有所不同。但直到上个月左右,我们的会话数据才出现任何问题。
  • 代码已经有 5 年历史了,但问题是从上个月开始的?值得一提:) ...您是否升级了任何东西(Apache、PHP、防火墙、代理)?它是特定的IE版本问题吗? (也许只有 IE 最新的用户?)
  • 我确实在 OP 中提到了它 :) 我询问了托管服务提供商是否有任何改变可能导致这些问题,但他们说没有。此外,它只是使用 IE 的用户,而不是所有使用 IE 的用户。我已经确认了 IE7 和 IE9 的报告,但是因为我自己无法复制问题,所以我不能肯定其他版本的 IE 没有问题。
【解决方案4】:

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

【讨论】:

  • cookie 持续时间/配置已在 cmets 中处理。 IE F12 开发者工具就可以了。提琴手不是必需的。
  • 相关信息应该是有问题的,而不是在 cmets 中。顺便说一句,我在 cmets 中没有看到 php.ini 部分。 IE 开发者工具无法保存完整的请求日志。
猜你喜欢
  • 2012-05-03
  • 1970-01-01
  • 1970-01-01
  • 2020-05-20
  • 1970-01-01
  • 2012-09-23
  • 1970-01-01
  • 1970-01-01
  • 2020-01-20
相关资源
最近更新 更多