9

我有一个主域:main.com、子域:test1.main.comtest2.main.com其他域one.comtwo.com.

现在它是这样完成的:

ini_set("session.cookie_domain", ".main.com");

$domain = 'main.com';

登录.php

$user = $db->query("SELECT id, login FROM users WHERE email=? AND password=?", 
array($email, $password), "rowassoc");

if($user)
{
  $_SESSION['user_id'] = $user['id'];
  $_SESSION['user_name'] = $user['login'];

  $time = 100000; 

  setcookie('email', $email, time() + $time, "/", "." . $domain);
  setcookie('password', $password, time() + $time, "/", "." . $domain);

  header('Location: http://' . $user['login'] . "." . $domain);
  exit;
}

在每个页面上添加:

if(!isset($_SESSION['user_id']))
{
  if(isset($_COOKIE['email']) && isset($_COOKIE['password']))
  {
    $email = $_COOKIE['email'];
    $password = $_COOKIE['password'];

    $user = $db->query("SELECT id, login FROM users WHERE email=? AND password=?",
    array($email, $password), "rowassoc");

    if($user)
    {
      $_SESSION['user_id'] = $user['id'];
      $_SESSION['user_name'] = $user['login'];
    }
  }
}
else
{
  $user = $db->query("SELECT id, login FROM users WHERE id=?", 
  array($_SESSION['user_id']), "rowassoc");


  if(!$user)
  {
    setcookie('email', '', time() , "/", "." . $domain);
    setcookie('password', '', time() , "/", "." . $domain);
    unset($_SESSION['user_id']);

    session_destroy();
    setcookie("PHPSESSID","",time(), "/", "." . $domain);
  }
  else
  {
    $_SESSION['user_id'] = $user['id'];
    $_SESSION['user_name'] = $user['login'];
  }
}

注销.php

if(isset($_SESSION['user_id']))
{
  setcookie('email', '', time() , "/", "." . $domain);
  setcookie('password', '', time() , "/", "." . $domain);
  unset($_SESSION['user_id']);
  unset($_SESSION['user_name']);

  session_destroy();
  setcookie("PHPSESSID","",time(), "/", "." . $domain);

  header('Location: /main');
  exit;
}

但它仅适用于域main.com及其子域test1.main.comtest2.main.com.

我需要以某种方式保存会话和其他域one.comtwo.com.

如何最好地进行安全身份验证,如果有解决方案,我真的很困惑,请举例说明。

4

3 回答 3

12

据我所知,子域之间的交叉会话很好,但它不会延续到一个全新的域。为此,您需要某种集中式数据方法或 API。

数据库方法:您必须创建一个远程 MySQL 数据访问,以便 domain2.com 可以访问 domain1.com 上的数据库。执行登录时,不仅应该创建一个新会话,而且应该将唯一的登录令牌(具有到期时间)放入 mysql 数据库中。现在,对于从 domain1.com 到 domain2.com 的每个链接,您应该添加一个包含随机生成的会话 id 的 $_GET 变量(md5 散列即可)。domain2.com 收到访问者后,将获取 $_GET 变量,通过 MySQL 数据库运行它以查找登录令牌,如果匹配,则认为该用户已登录(并且可能嵌入 $_COOKIE 作为很好地存储登录数据)。这将使登录可以在两个完全不同的域之间转移。

API 方法:您需要创建一个 API 方法,以便 domain1.com 可以响应来自授权域的外部请求,以在用户被转发时检索登录令牌。此方法还要求从 domain1.com 到 domain2.com 的所有链接都附加一个 $_GET 变量以传递唯一的会话哈希。然后在接收到访问者时,domain2.com 将对 domain1.com/userapi.php(或任何你称之为文件的文件)发出 curl() 请求,并且应该根据数据库中的内容测试变量。

这是我能解释的最好的了。用代码写出来是一项重要的工作,所以我不能提交。但是从你的代码来看,你对 PHP 有很好的理解,所以我相信你会成功的!

祝你好运朋友。

于 2010-11-03T22:27:10.450 回答
2

但是如果用户直接访问域one.com,则one.com无法通过上面提到的正确答案知道用户是否登录,似乎必须使用一些额外的js,它是jsonP!我们让account.main.com/userLoginStat.php?callback=loginThisDomain检查用户是否登录了 main.com,如果是,则 js 回调函数loginThisDomain做一些事情来自动登录用户到 one.com。

于 2012-06-04T06:09:07.140 回答
2

为了让您的会话跨越多个域,您需要使用session_set_cookie_params()。有了它,您可以指定您的域。例如...

session_set_cookie_params(10000, "/", ".main.com");

这会将站点根目录下的所有文档以及 main.com 的所有子域的会话超时设置为 10,000 秒。

你应该session_set_cookie_params()先打电话session_start()

于 2010-11-03T22:18:48.683 回答