7

在我们的网站上,我们希望能够跨多个域共享会话。所有这些网站都在同一台服务器上,但其中一些具有不同的 IP 地址。

我找到的可能解决方案是自己设置会话 ID:

<?php
session_id($someUniqueHash);
?>

如果我制作像 md5('test') 这样的散列,这很有效。在同一台服务器上的另一个域上,我们再次进行了会话。

问题是生成 ID。我在互联网上看到了一些带有 microtime 等的解决方案,但是当我使用这种方法时,我无法预测其他域/PHP 页面上的会话 ID。

有人有想法吗?或者我们不应该实施这个吗?是否有其他选项可以在多个域上共享会话?(不是子域!)

4

5 回答 5

5

我已经通过使用OAuth类型流实现了这个系统,但是我们用用户替换了消费者。

因此,每个域都会在其自己的会话中拥有经过身份验证的 Access_Token。然后,您将使用该 Access_Token 从 api 获取有关用户的信息。

我还使用session_set_save_handler解决了会话问题,并将会话存储在数据库表中......该表也将具有 Access_Token,使得使用数据库查询查找会话变得非常容易。

希望这有助于想法。

于 2012-10-16T00:22:31.120 回答
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'];
}

?>
于 2012-06-23T20:20:40.413 回答
0

嗯,这是一个困难的。

众所周知,当用户返回您的站点并且没有跨域 cookie 的方法时,PHP 使用 cookie 来理解 session_ids:跨域 cookie (编辑:有,但方法很复杂)。

这可能就是为什么我从来没有见过一个网站实现这个,即使他们有不同的域。

您可以通过页面上的链接从一个域通过 $_GET 或 $_POST 将会话 ID 传递到下一个域。如果用户直接进入您的其他站点,这将不起作用。

我能想到的唯一部分(不可靠)的方法是在数据库中记录用户计算机并使用它来了解它附加到哪个会话。因此,您将计算机的 IP 地址以及可能的其他一些详细信息保存在会话中。

个人计算机的 IP 和其他详细信息会将他们登录到其他域。

于 2012-06-22T11:41:16.833 回答
0

也许这不是你的选择,但你可以试试这个。

在您的主站点上,您可以正常生成会话 ID,并将会话永久保存到另一个域,您可以在 URL 中包含带有会话 ID 的图像标签。作为响应,另一个域将设置一个 cookie,这样当访问者来到那里时,它就已经知道会话 ID。

感觉有点聪明的裤子解决方案,但如果您没有太多其他域,它应该可以工作:) 顺便说一句,可以在浏览器中单独禁用第三方 cookie,这需要考虑。

哦,顺便说一句,会话采用(通过查询参数接受 id 并设置 cookie)是微妙的东西,应该受到保护,即会话必须在设置 cookie 之前已经存在。

于 2012-06-22T11:59:26.233 回答
0

If these are login sessions, consider using a single sign on (SSO) solution such as those that implement the SAML standard.

于 2018-05-22T15:18:05.653 回答