【问题标题】:PHP 5.3.3 - running session_start() in subdirectory kills existing sessionPHP 5.3.3 - 在子目录中运行 session_start() 会终止现有会话
【发布时间】:2012-01-02 06:01:21
【问题描述】:

自从不久前我的虚拟主机升级到 PHP 5.3.3 后,我一直在努力寻找一些烦人的会话问题。我已经确定如果存在活动会话,则从子目录调用 session_start() 会终止现有会话。例如,我开始一个会话并且用户登录到 domain.com/index.php 然后用户导航到 domain.com/members/ 这会触发 start_session() ...用户的会话丢失了。

我已经为此进行了挖掘,但找不到类似的东西。是否有可以解决这种行为的 PHP 配置?

【问题讨论】:

  • 这是一个您应该向您的主机提出的问题,配置因主机而异,有点无法回答。
  • 我也在走这条路——但到目前为止还没有很多运气。
  • 我认为在大多数情况下 PHP 会话将是每个域,而不是每个目录。
  • 什么是 cookie 设置(例如 session_set_cookie_params() 设置)?

标签: php session


【解决方案1】:

使用该版本的 PHP 多次调用 session_start() 应该不会导致任何问题,但还有其他可能的原因。

一种可能的解释是客户端的浏览器没有将会话 ID 发送回服务器。您可以通过比较两个页面生成的会话 ID 来测试这一点。假设您有一个可以正确测试的受控环境,您可以使用session_id() 获取会话。

也可能是用户访问了不同的网络服务器。由于(默认情况下)PHP 将会话存储到磁盘,因此多个服务器无法共享会话信息。如果这是一个共享主机,这可能不太可能是原因。但是,您可以使用phpinfo() 对此进行测试。它应该为您提供足够的信息来确定它是否是同一台服务器。对于多服务器系统,我会考虑将会话存储在 memcache 或 mysql 中。

【讨论】:

  • 好主意。会话 ID 被保留,但当我在子目录中运行 session_start() 时,$_SESSION 全局数组被清空。作为测试,我创建了一个简单的脚本,我在根目录和 /includes 目录中复制了该脚本。在根目录中触发时,会话被保留并打印会话数组。在子目录中,会话 ID 保持不变,但会话数组为空。
  • session_name()也一样吗?
【解决方案2】:

如果您的会话在同一目录中正常工作(您的问题尚不清楚),那么这种行为的唯一可能原因是,一个非常明显的原因:“目录”cookie 参数。
除了会话 cookie 参数的默认“/”之外,它似乎设置为有些不寻常的值。
你必须检查一下。

无论如何,如果没有 HTTP 交换日志,尝试任何与会话/cookie 相关的问题几乎是没有用的。
您必须使用一些 HTTP 嗅探器,例如 LiveHTTPHeaders Firefox 插件,以查看服务器发送的 cookie 标头以及客户端返回的标头。
否则一切都将在黑暗中拍摄。


好的,从您的评论看来,会话 ID 保持不变,因此,没有 HTTP 问题可能是原因。这个问题变得有点难以发现。 你能把你的测试脚本贴在这里吗?

【讨论】:

  • 正如我所说的 - 基本测试脚本。对于现有会话,在根目录中触发它会保留会话数组。在子目录中,会话数组丢失。在这两种情况下,都会保留会话 ID。 session_start();print_r($_SESSION);echo session_id();
  • errr... 你在哪里设置会话内容?您是否在根目录和子目录中运行相同的测试脚本?
  • 会话内容是在 root 中触发的登录脚本上设置的。我确实通过在测试脚本的根版本中有条件地设置$_SESSION['test'] = 'test'; 并绕过登录脚本来消除该脚本。
  • 不管怎样,包括 Safari 和 Chrome 在内的大多数 webkit 浏览器在 web 检查器的“网络”选项卡中都有很好的登录。它将显示为页面加载发送/接收的每个标题。
  • @SDG 请创建一个 DISTINCT 版本的测试代码。无需干预您的其他代码。
【解决方案3】:

我花了很长时间搜索、尝试和测试看似相同的问题。由于谷歌一直将我发送到这里,我认为分享解决方案可能对其他人有所帮助(尽管我在 2011 年的问题上发帖感觉很奇怪):

/bar.php 中设置的会话变量未在/foo/foobar.php 中设置。

当我最终发现http://www.example.com/bar.php 中的链接指向http://example.com/foo/foobar.php(缺少www)时,它意识到问题与文件夹/子文件夹无关。

更正html链接中的URL解决了这个问题。没有时间深入挖掘,我能弄清楚的是 (在我的配置中) Apache 没有区别,并且在有和没有 www 的情况下无差别地服务页面,而 PHP 不共享会话它认为是两个不同的域,example.comwww.example.com

【讨论】:

  • 拯救了我的一天!非常感谢。
【解决方案4】:

是否有可以解决这种行为的 PHP 配置?

是的,如果会话数据的存储在这些调用之间不同,$_SESSION 的内容也会不同。可以配置存储,请参阅http://php.net/manual/en/session.configuration.php 了解会话的所有配置选项。

如果 PHP 无法读取会话存储,你也会得到一个空数组。

我不能告诉你这是否是你的问题,但它可能会有所帮助。

顺便说一句,调用session_start() 而不是空的$_SESSION 通常表明新会话已创建。如果您在会话中使用 cookie 并输出 headers_listDocs,则可以验证这一点:

echo '<pre>', var_dump(headers_list());

如果它包含会话的新 cookie,则会话已使用此请求创建。

【讨论】:

    【解决方案5】:

    这里有很多好的建议。感谢大家。我花了一个周末的大部分时间来研究这个问题,但无法直接解决它。我最终向我的虚拟主机证明了这个问题发生在他的两个托管站点上,并且不会发生在 PHP 的默认安装中。为了解决这个问题,我最终将所有登录和会话逻辑移到了一个类中。

    【讨论】:

      【解决方案6】:

      想分享另一个答案,在这个 SO 中找到:Session variables not accessible in subdirectoryclayRay 回答。

      我的回答是我在根目录中保存了一个自定义的“php.ini”文件,将这些指令移动到ini_set() 调用中解决了它。如果您的主机允许,您也可以将它们推送到.htaccess

      【讨论】:

        猜你喜欢
        • 2015-11-06
        • 2012-08-01
        • 1970-01-01
        • 2011-05-13
        • 1970-01-01
        • 2014-07-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多