【问题标题】:PHP cookie and session values not recognized on first attempt第一次尝试时无法识别 PHP cookie 和会话值
【发布时间】:2015-09-12 13:48:19
【问题描述】:

好的,这是我的第二次尝试,用一种新的、更加孤立和简洁的方式来展示这个问题。问题与登录系统有关,其中会话变量似乎在第一次尝试时没有保存。但这里是演示错误行为的精简代码:

<?php

session_start();

echo "POST superglobal: <pre>" . print_r($_POST, true) . "</pre><hr/>";
echo "SESSION superglobal: <pre>" . print_r($_SESSION, true) . "</pre><hr/>";
echo "COOKIE superglobal: <pre>" . print_r($_COOKIE, true) . "</pre><hr/>";

$_SESSION['session_var'] = "SESSION VAR AVAILABLE";
setcookie("cookie_var", "COOKIE VAR AVAILABLE");

?>  
<html>
    <body>
        <form action="" name="frmPost" method="POST">
            <input type="submit" name="cmdSubmitPost" value="Submit" />
        </form>
    </body>
</html>

在我本地计算机上的本地主机上,以下是这段代码产生的结果:

初始页面加载后:

POST superglobal:
Array
(
)

SESSION superglobal:
Array
(
)

COOKIE superglobal:
Array
(
)

[Submit]

点击Submit一次后:

POST superglobal:
Array
(
    [cmdSubmitPost] => Submit
)

SESSION superglobal:
Array
(
    [session_var] => SESSION VAR AVAILABLE
)

COOKIE superglobal:
Array
(
    [cookie_var] => COOKIE VAR AVAILABLE
    [PHPSESSID] => hpkpft4hh1tqlm6e3r496bt5j2
)

[Submit]

这正是我所期望和需要的。我还临时注册了两个独立的免费 php 托管站点来测试这一点,它们都产生了与上述相同的结果。

但是,在我的主要托管环境 Arvixe,结果却有所不同。它是这样的:

初始页面加载后:

POST superglobal:
Array
(
)

SESSION superglobal:
Array
(
)

COOKIE superglobal:
Array
(
)

[Submit]

点击Submit一次后:

POST superglobal:
Array
(
    [cmdSubmitPost] => Submit
)

SESSION superglobal:
Array
(
)

COOKIE superglobal:
Array
(
)

[Submit]

第二次点击Submit后:

POST superglobal:
Array
(
    [cmdSubmitPost] => Submit
)

SESSION superglobal:
Array
(
    [session_var] => SESSION VAR AVAILABLE
)

COOKIE superglobal:
Array
(
    [cookie_var] => COOKIE VAR AVAILABLE
    [PHPSESSID] => 2k6ldfl2icdtj1k7sq5dc9qmj3
    [VC-NoCache] => 1
    [_asomcnc] => 1
)

[Submit]

我希望在 localhost 和其他临时免费 php 托管环境中创建的结果排除了相当简单的代码中的任何根本缺陷。

好的,现在问题是:在 Arvixe 托管环境中,为什么页面在第一次提交后无法识别 cookie 和会话值?我很确定真正的问题是为什么在第一次提交后无法识别 cookie 值? (这是真正的问题,因为这回答了为什么无法识别会话值......这是因为尚未识别 PHPSESSID cookie)。

php.ini 值基本相同,但如果有特定值可能有助于在此处发布,请告诉我哪些值。

另外,我认为这个问题的答案将有效地解决其他三个 stackoverflow 问题:

PHP cookie will not set until the page reloads TWICE. What's going on?

php session variable not stored at first attempt, working fine from second attempt

session variables not set the first time

(那里的解决方案都不适合我)

【问题讨论】:

  • 我认为您应该包含完整的代码,而不是条带化的代码(仅是相对的),因为这看起来像是某种其他错误逻辑的条件
  • 但是完整的代码非常庞大。这基本上是我将隐藏字段写入包含令牌的表单的情况,该令牌也写入会话。然后当表单发布时,我比较两者以确保帖子来自我的表单(即防止 CSRF 攻击)。它总是在第一次通过后返回“无效”(因为它没有看到会话变量)。第二次起作用了。与这里的精简(但功能齐全的代码)相同。在这里我们绝对可以看到失败。
  • 我在这里提出的案例排除了错误的逻辑,因为它在 localhost 和其他两个测试 php 主机环境中的功能完全符合预期。

标签: php session cookies


【解决方案1】:

虽然我从未使用过Arvixe,但我在开发过程中遇到过几次这个问题。我绝不是专家,但这是我的研究和经验,也是编码错误之外的两个主要原因。

Cookie 不会根据请求立即创建

刷新页面时,新创建的 cookie 不会立即可用。我之前在使用 SESSION_ID 和 cookie 时遇到过这种意外行为。例如,如果您在一个请求中设置了 cookie,则它在服务器的下一个请求之前将不可用(因此在您设置 cookie 后的下一次刷新)。 Accessing $_COOKIE immediately after setcookie()

也可能存在奇怪的逻辑和浏览器缓存网页的方式,我认为这很可能是这里发生的事情。

PHP 会话未设置 - 通过。 wwwnon-www 问题

您说它发生在您的Arvixe 环境而不是本地主机上?当您点击提交时,您应该检查域(删除或添加 www)是否正在更改。如果您在htaccess 中没有正确的规则或通过ini_set 或 PHP 中的其他配置设置设置,那么您可能会获得两个 session_id。我无法从您的代码中清楚地看出,但如果是这种情况,它将解释为什么您只第二次得到它(因为第一次提交它会加载新域并设置 session 变量和 cookie 变量) .您的服务器可能会将www 视为一个新的子域,而不选择共享cookie 和session_id,而是创建一个新的。尝试进入Console 并执行document.cookie 以获取有关它是否正在更改的信息。

Allow php sessions to carry over to subdomains

无关的session 命令或其他原因

如果您在页面上有任何 PHP 命令会摆弄 session_id,例如重新生成它或例如:

session_regenerate_id()
session_write_close()

这些命令可能会影响您的会话并导致意外行为。由于它是特定于案例的,因此您最好进一步阅读有关会话如何传播和处理的文档。除此之外,它可能是缓存、浏览器、标头、会话位置、陈旧会话、以前的 cookie 和其他相关问题。

【讨论】:

  • 感谢瓦尔基里!实际上,我现在几乎可以肯定“奇怪的逻辑和浏览器缓存网页的方式”是其根源,并怀疑答案在 htaccess 文件中的某个地方。不幸的是,我对 htaccess 设置几乎一无所知。支持缓存理论,当我将“?nocache=1”附加到 URL 时,它在 Arvixe 上可以正常工作。
【解决方案2】:

如果代码完全相同,那么环境就是原因。做一个 phpinfo();针对不同的托管环境。复制结果页面并运行差异比较。这将向您展示 PHP 的主机安装中可能存在的不公平现象。

没有人能够通过查看您的代码(无论是否不完整)来解决托管环境的问题。

【讨论】:

  • 我只是希望有更多 PHP 经验的人会看着并说,“哦,是的,我遇到了这种情况......你可以做的是添加一个 'ini_set(xxxxxx); '那将.....”我已经比较了 phpinfo() 输出,寻找可能导致这种情况的设置,并且没有任何东西跳出来(并且有数百行输出,所以我敢肯定没有人会想看到这一切)。
  • 你可能不想相信你的眼睛,因为它可以像缓存或会话处理程序一样简单。您只是想消除版本、已安装库或服务器配置中的任何差异作为原因。尝试 winmerge 或其他差异工具。 winmerge.org/?lang=en
  • 另外,当您进行测试时,不要使用页面重新加载。始终保持一致并仅在地址栏中使用新的写入。您通过表单的发布程序也必须被清除,并且页面重新加载不会这样做。
【解决方案3】:

感谢大家的意见。对于以后可能正在搜索此答案的任何人,事实证明问题出在托管/服务器端。

在实际切换主机后(需要的不仅仅是这个问题)同样的问题跟着我到新主机。但是在新主机上,他们的服务器设置包括一种称为“清漆缓存”的东西,这与客户端浏览器缓存非常不同。它是服务器端缓存。

据说它可以提高性能...但如果您的应用严重依赖经常更改的实时 cookie 和会话值,那真的会搞砸!

我敢打赌,我在上面链接的其他堆栈溢出帖子是由这个引起的。

在新的托管环境中,我刚刚关闭了所有“清漆缓存”,一切都运行良好。我怀疑旧主机有一些像这样的服务器端缓存。

【讨论】:

    猜你喜欢
    • 2013-01-20
    • 2013-12-19
    • 1970-01-01
    • 1970-01-01
    • 2012-08-03
    • 2013-12-31
    • 1970-01-01
    • 1970-01-01
    • 2012-06-10
    相关资源
    最近更新 更多