我找到的可能解决方案是手动设置会话ID:
<?php
session_id($someUniqueHash);
?>
如果我像md5('test')那样创建哈希,则可以正常工作。在服务器上的另一个域中,我们再次拥有会话。
问题在于生成ID。我在互联网上看到了一些解决方案,例如使用微秒等,但是当我采用该方法时,无法预测其他域/ PHP页面上的会话ID。
有人有想法吗?或者我们不应该实施这个功能?是否有其他选项可以在多个域之间共享会话?(不是子域!)
<?php
session_id($someUniqueHash);
?>
如果我像md5('test')那样创建哈希,则可以正常工作。在服务器上的另一个域中,我们再次拥有会话。
问题在于生成ID。我在互联网上看到了一些解决方案,例如使用微秒等,但是当我采用该方法时,无法预测其他域/ PHP页面上的会话ID。
有人有想法吗?或者我们不应该实施这个功能?是否有其他选项可以在多个域之间共享会话?(不是子域!)
我使用了OAuth类型的流程来实现这个系统,但我们用用户替换了消费者。
因此,每个域都会在自己的会话中拥有已认证的Access_Token。然后,您可以使用该Access_Token从api获取有关用户的信息。
我还使用session_set_save_handler解决了会话问题,并将会话存储在数据库表中......该表也会有Access_Token,使得通过DB查询轻松查找会话。
希望这能帮助您思考。
单独配置每个站点:
<?php
$cfgsession['file'] = "../sessions_global.txt";
$cfgsession['keepalive'] = 7200;
?>
$cfgsession['file']
。
在向另一个域发出请求时,包含来自一个站点的会话(可能是由Jack推荐的),只要您不抓住他们在其他浏览器或其他地方进行请求(请采取措施防止会话劫持),就可以让他们使用$_GET指定会话。例如:include ("../session.php");
if (isset($_COOKIE['session'])) session_begin($_COOKIE['session'], $_SERVER['HTTP_USER_AGENT'] . "+" . $_SERVER['HTTP_ACCEPT_CHARSET'], $_SERVER['REMOTE_ADDR']);
else session_begin("", $_SERVER['HTTP_USER_AGENT'] . "+" . $_SERVER['HTTP_ACCEPT_CHARSET'], $_SERVER['REMOTE_ADDR']);
setcookie("session", session_identity(), 0);
然后只需编写自己的session_函数:
<?php
function session_begin($mysession = "", $key = "", $client = "") {
global $cfgsession;
if (!preg_match("/^[a-z0-9]{32}$/i", $mysession)) $mysession = md5(microtime());
$error = false;
$client = trim($client);
$key = trim($key);
$cfgsession['returning'] = false;
if ($chandle = @tmpfile()) {
if ($shandle = @fopen($cfgsession['file'], "rb")) {
flock($shandle, LOCK_SH);
fputs($chandle, $mysession . " " . time() . " $" . $client . " $" . $key . "\n");
while (!feof($shandle)) {
$sline = explode(" ", trim(fgets($shandle)), 4);
if ($sline[1] >= (time() - $cfgsession['keepalive'])) {
if (($sline[0] == $mysession) && ($sline[3] == "$" . $key)) {
$cfgsession['client'] = substr($sline[2], 1);
$cfgsession['returning'] = true;
} elseif (count($sline) > 2) fputs($chandle, implode(" ", $sline) . "\n");
}
}
fclose($shandle);
fseek($chandle, 0);
if ($shandle = @fopen($cfgsession['file'], "cb")) {
if (flock($shandle, LOCK_EX)) {
ftruncate($shandle, 0);
$cfgsession['count'] = 0;
while (!feof($chandle)) {
$cline = trim(fgets($chandle));
fputs($shandle, $cline . "\n");
$cfgsession['count']++;
}
} else $error = true;
fclose($shandle);
} else $error = true;
} else $error = true;
fclose($chandle);
} else $error = true;
if (($cfgsession['returning'] == false) && ($mysession == $cfgsession['session'])) {
$cfgsession['returning'] = true;
$mysession = md5(microtime());
}
$cfgsession['session'] = $mysession;
if ($error) return -1;
else return 0;
}
function session_count() {
global $cfgsession;
return $cfgsession['count'];
}
function session_client() {
global $cfgsession;
return $cfgsession['client'];
}
function session_id() {
global $cfgsession;
return $cfgsession['session'];
}
function session_index() {
global $cfgsession;
$index_return = array();
if ($uhandle = @fopen($cfgsession['file'], "rb")) {
flock($uhandle, LOCK_SH);
while (!feof($uhandle)) {
$uline = explode(" ", trim(fgets($uhandle)), 4);
foreach ($uline as &$value) {
if ($value[0] == "$") $value = substr($value, 1);
}
if (count($uline) >= 2) $index_return[] = $uline;
}
fclose($uhandle);
}
return $index_return;
}
function session_returning() {
global $cfgsession;
return $cfgsession['returning'];
}
?>
嗯,这是一个困难的问题。
众所周知,PHP使用cookie来理解当用户返回您的站点时的session_id,而且没有跨域cookie的方法:跨域cookie(编辑:有,但方法很复杂)。
这可能就是为什么我从未见过一个站点实现这个功能,即使它们有不同的域名。
您可以通过页面上的链接从一个域传递会话ID到下一个域,通过$_GET或$_POST。如果用户直接进入您的其他站点,则无法使用此方法。
我能想到的唯一部分(不可靠)的方法是在数据库中记录用户计算机,并使用它来了解附加到其上的会话。因此,您可以存储计算机的IP地址和其他一些详细信息,并将其与会话相关联。
人们计算机的IP和其他详细信息将使他们登录到其他域。
也许这对你来说不是一个选项,但你可以尝试一下。
在你的主站点上,按照正常方式生成会话 ID,并在 URL 中包含带有会话 ID 的图像标签,以延续会话到另一个域。作为响应,另一个域将设置一个 cookie,因此当访问者到达那里时,它已经知道会话 ID。
感觉有点聪明,但如果你没有太多其他域的话,它应该能够工作 :) 顺便提一下,第三方 cookie 可以在浏览器中单独禁用,这是需要考虑的事情。
顺便说一下,会话采用(通过查询参数接受 ID 并设置 cookie)是非常敏感的事情,必须受到保护,即在设置 cookie 之前必须已经存在会话。