在我们的网站上,我们希望能够在多个域中共享会话。所有这些网站都在同一台服务器上,但其中一些网站有不同的IP地址。
我找到的可能解决方案是自己设置会话ID:
<?php
session_id($someUniqueHash);
?>
如果我像md5('test')那样制作哈希,这就行了。在同一服务器上的另一个域上,我们再次进行会话。
问题在于生成ID。我在互联网上看到一些使用microtime等的解决方案,但是当我使用这种方法时,我无法预测其他域/ PHP页面上的会话ID。
有没有人有想法?或者我们不应该实现这个?是否有其他选项可以在多个域上共享会话? (不是子域!)
答案 0 :(得分:4)
我使用OAuth类型流程实现了此系统,但我们将用户替换为消费者。
因此,每个域在其自己的会话中都将具有经过身份验证的Access_Token。 然后,您将使用该Access_Token从api获取有关用户的信息。
我还使用session_set_save_handler解决了会话问题并将会话存储在数据库表中......此表也具有Access_Token,这使得使用数据库查询找到会话非常容易。
希望这有助于提出想法。
答案 1 :(得分:0)
嗯,这很难。
众所周知,当用户回到您的网站并且无法跨域cookie时,PHP使用cookie来理解session_id:Cross domain cookies(编辑:但方法很复杂)。
这可能就是为什么我从未见过网站实现这一点,即使它们有不同的域名。
您可以通过页面上的链接从一个域通过$ _GET或$ _POST将会话ID传递给下一个域。如果用户直接进入您的其他网站,则无法使用此功能。
我能想到的唯一部分(不可靠)方法是在数据库中保留用户计算机的记录,并使用它来了解将其附加到哪个会话。因此,您可以存放计算机的IP地址,也可能包含一些其他详细信息,并将其备份到会话中。
人员计算机的IP和其他详细信息会将其记录到另一个域中。
答案 2 :(得分:0)
也许这不是你的选择,但你可以试试这个。
在您的主站点上,您可以按照正常情况生成会话ID,并将会话永久保存到另一个域,您可以在URL中包含会话ID的图像标记。作为回应,另一个域将设置一个cookie,以便当访问者到达那里时它已经知道会话ID。
感觉有点聪明的裤子解决方案,但它应该工作,如果你没有太多的其他域:)第三方cookie可以在浏览器中单独禁用btw,需要考虑的事情。
哦顺便说一句,会话采用(通过查询参数接受id并设置cookie)是很微妙的东西,应该受到保护,即在设置cookie之前会话必须已经存在。
答案 3 :(得分:0)
单独配置每个站点:
<?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'];
}
?>
答案 4 :(得分:0)
如果这些是登录会话,请考虑使用单点登录(SSO)解决方案,例如那些实施SAML标准的解决方案。