【问题标题】:PHP creating new session with each reloadPHP在每次重新加载时创建新会话
【发布时间】:2011-07-25 11:19:27
【问题描述】:

对于我的网站,会话管理大部分都可以正常工作。会话在以后创建、保存和使用都没有问题。

但是当代码使用 session_start() 时,它总是会创建新的、完全空的会话。下面有问题的代码。

header('Content-Type: text/html; charset=UTF-8');

$main_domain = $_SERVER["HTTP_HOST"];
$expld = explode('.', $main_domain);

if(count($expld) > 2) {
   $tld = array_pop($expld);
   $domain = array_pop($expld);
   $main_domain = $domain . "." . $tld;
}

session_set_cookie_params (0, '/', $main_domain);
session_name('sid');
session_start();
echo session_id();
exit;

执行此脚本时,会在每次重新加载时创建新会话。

smar@ran ~> ls /tmp/sess_* | wc -l
10
smar@ran ~> ls /tmp/sess_* | wc -l
11
..
smar@ran ~> ls /tmp/sess_* | wc -l
17

但只有其中一个会话中有任何数据,并被应用程序使用。

浏览器中的输出总是相同的:87412d5882jr85gh5mkasmngg7,它是浏览器 cookie 中的 id 和 /tmp 中填充数据的会话 id。

此行为可能是什么原因?这些空文件并不是什么大问题,但它们确实使 /tmp(或会话目录)无缘无故地填充了很多。

编辑 1:

看起来这是与服务器相关的问题,因为它适用于某些人。我的配置是带有 Apache 和 PHP 5.3.6 的 Gentoo Linux(32 位)。

如果我强制它创建新会话(例如删除我自己的 cookie),它会创建 两个 会话文件而不是一个。如果它重用旧的,它会创建“仅”一个。

编辑 2:

会话配置,根据要求(所有配置行带有session.):

session.save_handler = files
session.save_path = "/tmp"
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.bug_compat_42 = On
session.bug_compat_warn = On
session.referer_check =
session.entropy_length = 0
session.entropy_file =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.hash_function = 0
session.hash_bits_per_character = 5

编辑 3:

更奇怪的是,我尝试使用 CLI 中的会话。在那里,没有设置会话 cookie,它总是创建一个新会话。当使用session_id() 设置固定会话值时,完全停止创建新会话并改用旧会话。

这种行为与 Apache 相同,所以我开始怀疑这是 PHP 中的错误。如果名称专门设置为session_id(),并且会话正确使用,则不会创建新会话。

更荒谬的是,当我从 $_COOKIE["PHPSESSID"] 获取 phpsessid 并将其设置为 session_id() 时,它又开始创建新的(无用的空会话)会话。

编辑 4:

由于我写得不够清楚:简单地拥有

session_start()

由于单个参数会导致此问题发生,因此它并非特定于我的代码。

【问题讨论】:

  • 会话时间呢?并尝试评论session_set_cookie_params (0, '/', $main_domain); 可能是其他地方女巫放置名为“sid”的会话
  • 如果您将 session_start 放在发送标头之前会发生什么...?
  • @Subdigger:是的,没用。即使是它所在的地方,它也不会在会话之前创建会话,所以我怀疑这是与服务器配置相关的东西。 更新问题
  • 我正在使用 Suhosin-Patch (cli) 运行 PHP 5.3.3-7+squeeze1(构建时间:2011 年 3 月 18 日 20:10:12),类似问题
  • 允许用户从/tmp 阅读不是安全漏洞吗?它是共享的,并且会话 ID 是可读的...

标签: php session


【解决方案1】:

Cookie 仅返回到它们设置所在的虚拟主机/路径。

由于您的路径是“/”,这意味着页面不是通过 $domain 请求的。 “。” . $tld;

例如用户通过 www.example.com 请求页面

cookie 是为 example.com 设置的

用户从 www.example.com 访问后续页面 - cookie 不在范围内。

来自RFC 2965

x.y.com 域匹配 .Y.com 但不匹配 Y.com。

实际上,如果您继续阅读,规范确实说如果没有提供,用户代理应该在主机前加上一个点,但是您进入了浏览器行为变化的领域。

如果您只是返回带有与请求匹配的虚拟主机的 cookie,它将按预期工作。

【讨论】:

  • 你说得对,我在 cookie 开头缺少点;浏览器似乎不需要它。这种爆炸的重点(在示例中可见以进行澄清)是在顶级域中设置 cookie,因此它们在子级域中也可见。 .foo.tld 会这样做,并且有效;会话有效,它只是为每次重新加载创建那些空文件。
  • 这是一个非常有用的信息,它在我的情况下澄清了这个问题,并解决了会话 ID 在重新加载时重新生成的问题。作为说明,我无法通过在主机前加上 .在大多数现代浏览器中似乎这被解释为无效的 url?谢谢 symcbean!
【解决方案2】:

使用session_start() 作为第一个会话命令,在所有其他session_*() 方法之前!

【讨论】:

  • 这只会禁用那些cookie设置,并不能解决问题。已经测试过,如问题的 cmets 所示。 (为了确定,我再次测试了)
  • 稍后在代码中设置会话不是问题,但您必须 1000% 确保在 session_*() 命令之前发送标头,并且不会收到任何 error_reporting 行。如果你没有类似的东西,你可以在任何你想要或需要的地方设置 session_*() :)
  • 简单的 session_start() 因为应用程序中只有一行会导致问题,所以我怀疑是不是这样。
【解决方案3】:

这与最初的原因不完全一样,但解决方法完全相同:每次重新加载都会定义新的会话 ID。

在这种情况下,错误是 Varnish,它被设置为将每个请求都设置为通过模式 (return (pass)),而不是缓存所有内容。结果,每个请求都到达后端,每次都会调用 session_start()。

但是当响应通过 Varnish 发送到客户端时,cookie 被从响应中删除。这是因为即使我们想要缓存站点,后端也会设置 cookie(会话 id 以及其他)。无论如何,cookie 被删除,客户端执行另一个请求并且没有传递任何 cookie(它从未收到任何 cookie!)并且 PHP 再次调用 session_start() 而没有任何会话 id...

在这种情况下,这更多是在识别错误​​时出现的错误,表现为创建了大量不必要的会话。如果一开始就启用了缓存,那么它们就不会被创建。

还有另一种方法可以创建这些会话:让浏览器完全不接受 cookie。愚蠢的原因,我知道,但它确实发生了......

对于最初的问题,自从离开原始开发机器后,我就再也没有遇到过。

【讨论】:

    【解决方案4】:

    我认为 powtac 在某种程度上是正确的,但 session_start(); 应该是你做的第一个操作,甚至在 header('Content-Type: text/html; charset=UTF-8'); 之前

    【讨论】:

      【解决方案5】:

      我不想成为泥潭中的棍子,但是您是否检查过/tmp 对 PHP 的可读性和可写性(在大多数情况下,这意味着 www-data 用户)?如果没有,请将会话保存位置移动到您可以写入的位置。

      【讨论】:

      • 是的,这不是问题所在。会话由 php 在那里创建,没有问题。
      • 好的,试试phpinfo(),看看是否有任何东西覆盖会话cookie域等或设置secure=1。 (我假设上面的会话配置来自 php.ini)
      • FWIW,这个问题是很久以前的问题,现在已经消失了,当我切换到另一个机器时,所以我不能再测试这个问题了。我从未对这些标志进行过更改,而我当时的配置是 Gentoo 的默认 PHP 配置,所以我也怀疑是不是这样。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-23
      • 2013-04-24
      • 2013-04-01
      • 2014-09-02
      • 2014-01-15
      相关资源
      最近更新 更多