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

如何在php中生成唯一的会话ID,php,session,sessionid,Php,Session,Sessionid,在我们的网站上,我们希望能够在多个域中共享会话。所有这些网站都在同一台服务器上,但其中一些具有不同的IP地址 我找到的可能解决方案是自己设置会话ID: <?php session_id($someUniqueHash); ?> 如果我像md5(“test”)那样做散列,这就行了。在同一服务器上的另一个域上,我们再次进行了会话 问题是生成ID。我在internet上看到了一些使用microtime等的解决方案,但是当我使用这种方法时,我无法预测其他域/PHP页面上的会话ID 有人

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

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

<?php
session_id($someUniqueHash);
?>

如果我像md5(“test”)那样做散列,这就行了。在同一服务器上的另一个域上,我们再次进行了会话

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


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

嗯,这是一个困难的问题

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

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

您可以通过页面上的链接从一个域通过$\u GET或$\u POST将会话id传递到下一个域。如果用户直接进入您的其他站点,则此操作将不起作用

我能想到的唯一部分(不可靠)的方法是在数据库中保存用户comptuer的记录,并使用该记录来了解连接到它的会话。所以你把计算机的IP地址和其他一些细节放在一个会话中


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

也许这不是您的选项,但您可以尝试一下

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

感觉有点聪明的解决方案,但是如果你没有太多其他域名,它应该工作:第三方cookie可以在浏览器BTW中单独禁用,有些事情要考虑。p>


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

分别配置每个站点:

<?php

$cfgsession['file'] = "../sessions_global.txt";
$cfgsession['keepalive'] = 7200;

?>
然后只需滚动您自己的会话功能:

<?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'];
}

?>

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

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

我还解决了在数据库表中使用和存储会话的问题。。。这个表还具有Access_令牌,这使得使用DB查询查找会话非常容易


希望这有助于想法。

< P>如果是登录会话,请考虑使用单点登录(SSO)解决方案,例如实现SAML标准的解决方案。

为什么不让PHP为您生成会话ID?顺便说一句,您可以跨域共享会话ID。这可能是cookie的问题,也可能是传递查询参数的问题。查询参数不是首选的,它不安全,并且不支持url。据我所知,你只允许cookie访问同一个域(子域)而不是多个域。你传递的只是一个cookie。您可以为第三方域制作cookie,即所谓的第三方cookie。您可能还需要检查执行此操作的法律方面(在已解决的技术方面旁边)。顺便说一句,您可能想了解的所有技术细节:Tnx、Hakre。我还不知道。我会调查你的选择,并在这里作出回应。有一个网站是这样做的:例如。我知道他们的网站是用PHP开发的,所以这是可能的。但我担心这很难。我确实纠正了我的答案跨域cookie是可能的,但正如那篇文章中所说的那样可靠,但是跨域会话确实不可靠……我最近一直在考虑这样做。我想知道是否有关于存储和检索性能的案例研究或简单讨论,方法是将访问令牌添加到db表中,并在每个请求中查询它。
<?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'];
}

?>