对于我的网站,会话管理大多正常。会话可以在以后创建,保存和使用,而不会出现问题。
但是当代码使用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()
作为单个参数会导致此问题发生,它不是特定于我的代码。
答案 0 :(得分:2)
Cookie仅返回到设置它们的vhost /路径。
由于您的路径为'/',这意味着未通过$ domain请求页面。 “” 。 $ TLD;
e.g。用户通过www.example.com请求页面
为example.com设置了cookie
用户从www.example.com访问后续页面 - 该Cookie不在范围内。
来自RFC 2965
x.y.com域名匹配.Y.com但不是Y.com。
实际上,如果您继续阅读,那么规范会说用户代理应该在主机前面加上一个点(如果没有提供),但是你进入了浏览器行为不同的领域。
如果您只是使用与请求匹配的vhost返回cookie,它将按预期工作。
答案 1 :(得分:0)
在所有其他session_start()
方法之前使用session_*()
作为第一个会话命令!
答案 2 :(得分:0)
我认为powtac在某种程度上是正确的,但session_start();
应该是你的第一次操作,甚至在header('Content-Type: text/html; charset=UTF-8');
之前
答案 3 :(得分:0)
这与原始原因不完全相同,但分辨率完全相同:每次重新加载都会定义新的会话ID。
在这种情况下,故障是Varnish,它被设置为将每个请求置于通过模式(return (pass)
)而不是缓存所有内容。结果,每个请求都发送到后端,每次调用session_start()。
但是当响应通过Varnish发送给客户时,cookie就从响应中删除了。这是因为即使我们想要缓存网站,后端也会设置cookie(会话ID以及其他内容)。无论如何,cookie被删除,客户端做了另一个请求,并且没有传递任何cookie(它从未收到任何cookie!)然后PHP再次调用session_start()而没有任何会话ID ...
在这种情况下,这更容易识别错误,这可能是因为创建了大量不必要的会话。如果首先启用缓存,那么首先不会创建这些内容。
还有另一种方法来管理创建这些会话:让浏览器根本不接受cookie。愚蠢的原因,我知道,但确实发生了......
对于原始问题,我从原始开发机器移开后没有发现它。
答案 4 :(得分:0)
我讨厌成为泥巴,但你检查过/tmp
是否可由PHP读取和写入(在大多数情况下,这意味着www数据用户)?如果没有,请将会话保存位置移动到您可以写入的位置。