如何在php中生成唯一的会话ID

时间:2012-06-22 11:33:57

标签: php session sessionid

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

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

<?php
session_id($someUniqueHash);
?>

如果我像md5('test')那样制作哈希,这就行了。在同一服务器上的另一个域上,我们再次进行会话。

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

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

5 个答案:

答案 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标准的解决方案。