PHP在每次重新加载时创建新的会话


PHP creating new session with each reload

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

但是当代码使用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:

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

如果我强制它创建新的会话(比如删除我自己的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()

作为单个参数导致这个问题发生,它不是特定于我的代码。

cookie只返回到设置它们的vhost/路径。

由于您的路径是'/',这意味着页面不是通过$domain请求的。"。"。tld美元;

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

cookie设置为example.com

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

源自RFC 2965

x.y.com domain-match .Y.com但不匹配。

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

如果您简单地返回一个与请求匹配的vhost cookie,它将按预期工作

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

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

在这种情况下,错误是Varnish,它被设置为将每个请求都置于传递模式(return (pass)),而不是缓存所有请求。因此,每个请求都被发送到后端,在那里每次都调用session_start()。

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

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

还有另一种方法来管理创建这些会话:让浏览器根本不接受cookie。我知道这是愚蠢的理由,但它确实发生了……

对于原来的问题,自从从原来的开发机器移开以来,我没有绊倒过它。

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

我讨厌成为泥里的一根棒,但是你检查过/tmp是可读的和可写的PHP(在大多数情况下,这意味着www-data用户)?如果没有,请将会话保存位置移动到您可以写入的位置。