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

时间:2011-07-25 11:19:27

标签: php session

对于我的网站,会话管理大多正常。会话可以在以后创建,保存和使用,而不会出现问题。

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

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

5 个答案:

答案 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数据用户)?如果没有,请将会话保存位置移动到您可以写入的位置。