跨子域名保持会话变量

5
我一直在尝试在两个子域之间维护会话变量,但发现这是不可能的。最终我创建了两个最小化的PHP网页作为测试平台,其中一个我称之为"测试1"只设置了

$_SESSION['test'] = "Fred";

这段文字描述了一个测试过程,其中有一个超链接指向“test 2”,它会尝试回显$_SESSION['test']的值以证明是否成功。作者将“test 1”放在主域名下,而“test 2”则放在子域名下。作者从不同的来源中尝试了多个版本的头信息,以下是最主要的三个(当然还有它们的变种):
ini_set('session.cookie_domain',substr($_SERVER['SERVER_NAME'],strpos($_SERVER['SERVER_NAME'],"."),100));
session_start();

或者

ini_set('session.cookie_domain','mydomain.com');
session_start();

或者

ini_set('session.cookie_domain', PHP_INI_ALL);
session_start();

或者

session_set_cookie_params(0, "/", ".mydomain.com", false);
session_start();

我发现在每种情况下都得到了相同的结果。会话未跨子域传递,页面测试 2 不知道我将 $_SESSION['test'] 设置为什么值。然而,网络上似乎对上述方法中的其中一种应该起作用有足够的确定性。你有什么想法,特别是因为我正在使用最小的页面来测试机制(我看不到任何副作用)?顺便说一下,我在共享服务器上,如果这里有相关的内容。

谢谢你的想法。弗兰克。

编辑我修复了它。问题是由 Suhosin 引起的。请参见本页底部的详细答案。

2个回答

5

好的,我已经解决了这个问题,它是一个烂摊子。

Suhosin的suhosin.session.cryptdocroot选项是整个问题的根源。当会话加密密钥基于DocRoot时,导致基域和子域从不同目录提供服务时,子域无法看到彼此的会话变量。这导致服务器上的会话变量存储在不同的文件夹中,因此它们对应的域之间不可见。

解决方法。只需在您的php.ini文件中添加以下两行即可:

suhosin.session.cryptdocroot=Off
suhosin.cookie.cryptdocroot=Off

48小时的噩梦追踪,4.8秒即可修复。

48小时的噩梦来追踪,4.8秒就解决了。太好了,我明白你的意思 :) - qasanov

0

我已经让它工作了,设置了会话名称和会话cookie参数:

$some_name = session_name("some_name");
session_set_cookie_params(0, '/', '.some_domain.com');
session_start();

谢谢。我尝试给会话命名,但没有成功。不过现在我有更多的信息了。我按照php.net上的文档建议进行了一个测试,并添加了以下内容:$some_name = session_name("some_name"); $blnResult = ini_set("session.cookie_domain", ".mydomain.com"); session_start(); if (empty($blnResult) or (!$blnResult)) { echo "无法设置该项"; exit; } 我发现返回结果显示它没有被设置!你知道为什么会这样吗? - Frankie
@Frank Anderson,我还没有尝试过ini_set方法,只用了session_set_cookie_params - jeroen
谢谢Jeroen。我犯了一个笨拙的错误,但现在我已经纠正了,并且按照您在这里建议的设置进行了操作。但是,只要它在子域中,会话变量的值仍然无法传递到“接收”页面。还可能是什么问题,或者我可以尝试哪些其他诊断来找出问题所在? - Frankie
注意:我使用session_id()进行了检查,发现两个页面实际上具有相同的会话ID - 更奇怪的是,第二个页面的Session变量没有值!有什么想法吗? - Frankie
@Frank Anderson 当你在两个页面上执行 var_dump($_SESSION); 时,你看到了什么?结果完全不同吗? - jeroen
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接