【问题标题】:PHP session data changes in Internet ExplorerInternet Explorer 中的 PHP 会话数据更改
【发布时间】:2014-03-01 14:50:12
【问题描述】:

我已经定义了一个使用 PHP 存储令牌的会话,如下所示:

$_SESSION['token'] = sha1(uniqid(mt_rand(), true));

当我想阅读这个会话时,我在 Chrome 或 Firefox 中没有任何问题。但是在 IE 中,它会在重新生成之前更改为其他内容。例如,如果我将其值存储在表单的隐藏字段中并像这样提交:

<input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>" />

我会在下一页的IE中得到这个结果:

echo $_SESSION['token']; // shows 1b05fab5ec11f1d50713aea6e74f84727d29b4a3
echo $_POST['token']; // shows e8fac6d55b04d1752f37ecde953f7f08b112ccca

而如果我在创建后立即打印$_SESSION['token'],甚至在其创建页面结束时打印,它会准确显示内容并且没有问题。

这个问题是为了什么?

编辑:
这是我的表格:

<form action="process/login.php" method="post">
   <input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>" />
   <label>Email: </label><input type="text" name="email" />
   <div class="space"></div>
   <label>Password: </label><input type="password" name="password" />
   <div class="space"></div>
   <input type="submit" value="Login" class="button" />
</form>

【问题讨论】:

  • 您是否检查过 IE 上是否启用了 cookie? =/
  • 向我们展示将令牌放入 POST 数据中的代码
  • 您是否尝试将 $_SESSION['token'] 命名为其他名称?例如尝试 $_SESSION['my_app_token']。这样您就可以确保与其他应用程序/脚本没有冲突。
  • 页面是否在 iframe 内?

标签: php internet-explorer session


【解决方案1】:

由于 PHP 和会话存储是服务器端,而 IE 显然是客户端,所以问题不在于会话代码。

会话通常由 cookie(会话 cookie)或通过 POST/GET 变量跟踪。默认情况下,在 PHP 中这个值被命名为 PHPSESSID。

可能,在您的情况下,与您的服务器端会话相关联的会话 cookie 或 POST/GET 变量在 IE 中无法正常运行。如果是 cookie,它可能与 cookie 设置以及是否完全允许 ​​cookie 有关。如果是 POST/GET,则可能是您的 HTML 格式错误,IE 不喜欢这种方式,但其他浏览器可以理解。

现在,一旦在 IE 中丢失了该值,PHP 会在每个请求上为该浏览器分配一个新会话,并在每个请求上重新生成会话令牌。但是您的隐藏字段也会记住旧令牌...

如果您向我们展示更多代码(您可以编辑您的问题),我可以编辑我的答案为您提供更多详细信息。

编辑 您可以首先向我们展示有关会话和会话 cookie 的相关 php.ini 设置行。并通过仔细检查您的 IE cookie 设置。具体来说我想知道你是否设置了cookie_path,使cookie只在同一目录中可用。

也许您甚至安装了 IE 安全设​​置或插件来阻止 cookie。因此,请尝试检查您的 IE 设置并禁用所有加载项并再次测试。

还要检查第一页(设置会话)和第二页(读取会话)是否具有完全相同的域名。

因此,例如第一页中的www.yourdomain.com,不应该是第二页上的yourdomain.com(没有www)或www.yourdomain.com.(末尾有一个额外的点)。

【讨论】:

  • 感谢您的关注。会话和 cookie 没有问题。我创建了另一个会话$_SESSION['test']=123,并且在同一个场景中没有任何问题。当我发布它时,它的值与会话值相等。
  • 是的,但由于123 是一个固定字符串,您不知道它是否会在您第二次请求时被自己覆盖。我 95% 确信这是一个 cookie 问题...尝试使用 FF/Chrome 中的元素检查器和 IE 中的 F12 开发人员工具来查看 cookie。您可能不会在 IE 中看到它们,或者每次都看到不同的值。
  • 在 php.ini 中,我有这个:session.cookie_path = /。第一页和第二页在同一路径中。我在 IE 中也没有任何特殊的附加组件
  • 你已经停止回答了!
  • @MohammadBagherSaberi cookie 设置似乎没问题。一个好的跟进可能是:在 Firefox (FF) 和 Internet Explorer (IE) 中访问您的站点。并在 FF 中打开 Element Inspector,在 IE 中打开开发者工具。您可以通过在浏览器中按键盘上的 F12 键来打开它们。在他们两个去网络选项卡。现在刷新并查看页面加载的请求标头。 (忽略图像请求等)请特别注意名为 PHPSESSID 的 cookie 或 POST 参数。 ...然后转到您的第二页,并查找相同的 cookie/POST 参数。
【解决方案2】:

我认为在您的表单提交后,您可能会创建另一个令牌值。

使用

if(!isset($_POST['token'])){
  $_SESSION['token'] = sha1(uniqid(mt_rand(), true));
}

【讨论】:

  • 如果是这样,我猜它不适用于 chrome 或 firefox 上的 OP,他说问题是 IE 特定的。
  • 将 type="hidden" 替换为 hidden="yes"
  • @ViswanathPolaki 您的回答最终将导致 OP 在第二页或第三页请求中不再具有 $_SESSION['token'] 。而且您上面的评论真的很愚蠢,因为这在 HTML 中是不合法的,并且会使隐藏字段变得可见。
【解决方案3】:

我会尝试将输入的名称更改为其他名称,也许 IE 正在使用令牌名称做一些奇怪的事情。搜索了网络,但没有提到这一点,但为了安全起见,删除这个选项我会这样做。

<input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>" />

到:

<input type="hidden" name="my_session_token" value="<?php echo $_SESSION['token']; ?>" />

并尝试将$_SESSION['token'] 更改为$_SESSION['my_session_token'],如评论中所述

【讨论】:

  • 您是否尝试将$_SESSION['token'] 更改为$_SESSION['my_session_token'] 之类的其他名称??
  • 由于 OP 在所有浏览器中都为 $_POST['token'] 获取 some 值,因此该值的名称显然不是问题.
  • @nl-x 由于 OP 使用 $_SESSION['test'] 进行了测试,并且运行良好,所以除了命名问题之外我想不出任何其他问题。
  • @CodeBird 我不能 100% 确定。但是由于 OP 所做的测试是使用固定字符串123,所以恐怕它并不能证明任何事情。也许 OP 想用$_SESSION['test']=sha1(uniqid(mt_rand(), true));&lt;input type="hidden" name="test" value="&lt;?php echo $_SESSION['test']; ?&gt;" /&gt; 来排除这种情况?
  • @nl-x 是的,我认为这是他应该做的,只是为了确保简单的东西能正常工作。我的意思是,我总是喜欢先测试简单的东西,然后再做更复杂的东西
【解决方案4】:

我几乎可以肯定您分配了两次$_SESSION['token']。可能是同一行代码被执行了两次,或者您也将变量分配到了其他地方。为了找到问题,您需要定义一个函数作为分配会话条目的包装器。然后调用函数而不是直接分配变量。这是示例代码:

function assign_token()
{
    $_SESSION['token'] = sha1(uniqid(mt_rand(), true));
}

但您需要确保永远不要在代码中的任何位置直接分配token。并改为调用此函数。完成此操作后,如果您有调试器,您需要做的就是在此函数中设置一个断点,并查看它被调用了多少次以及从何处调用。

但如果您没有安装调试器,或者更糟糕的是,如果分配不是在一个请求中而是在两个请求中发生,您需要像这样修改您的函数:

function assign_token()
{
    file_put_contents('/tmp/assign_token.txt', time() ."\n". print_r(debug_backtrace(), true), FILE_APPEND);
    $_SESSION['token'] = sha1(uniqid(mt_rand(), true));
}

添加的行将帮助您跟踪每次调用该函数。即使它在两个单独的请求中被调用两次,您也可以通过FILE_APPENDtime() 识别它们。第一个附加到文件(显然),因此日志条目不会相互覆盖,第二个有助于了解您的日志的两个条目是否在同一个请求中生成。

这就是我所拥有的。最后,您可能希望设置日志条目的样式,使其更具可读性。

【讨论】:

  • 我没有创建两次$_SESSION["token"]。如果你的想法是正确的,我也必须在 FF 和 Chrome 等其他浏览器中看到问题。
  • 没有必要。也许更新会话的第二个请求仅在 IE 中发送!如果我是你,我会在进入更深层次之前考虑这种可能性。
【解决方案5】:

我会做更多的事情:

md5(uniqid($_SERVER['REMOTE_ADDR'], true))

确保令牌始终是唯一的。

【讨论】:

  • 真是个坏主意。很容易破解。并且仍然没有解释为什么存在问题。
【解决方案6】:

如果我错了,请纠正我,但我已经在 Chrome FF 和 IE 7 中测试了下面的代码,似乎 IE 没有任何问题。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <form method="POST" action="/">
            <?php
            session_start();
            if(!$_SESSION['token']){
                $_SESSION['token'] = sha1(uniqid(mt_rand(), true));
            }
            ?>
            <input type="hidden" value="<?php echo $_SESSION['token']; ?>" name="token"/>
            <button type="submit" name="send">Send</button>
            <?php
            if(!empty($_POST)){
                var_dump($_POST);
                var_dump($_SESSION['token']);
            }
            ?>
        </form>

    </body>
</html>

如果您的 php 版本 >= 5.4,请尝试使用以下命令 () 在 php 中设置内置服务器:

php -S localhost:88 -t /path/to/your/app

假设您在本地计算机上进行测试。也许您服务器上的 apache+php 堆栈有问题。

【讨论】:

  • 我看不出这会如何改变任何事情
【解决方案7】:

检查 sha1(uniqid(mt_rand(), true)) 的值。 IE 对包含“-”或“_”的名称有问题——它们无法维持会话!过去我遇到过两次这个问题,而且我总是需要几周的时间才能弄清楚,我很震惊 IE 还没有修复它。

只要确保你没有这样的字符!

【讨论】:

  • sha1 不是一个名字...它是一个值
猜你喜欢
  • 1970-01-01
  • 2015-11-03
  • 1970-01-01
  • 2011-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-01
  • 1970-01-01
相关资源
最近更新 更多