具有多个域和子域的 PHP 身份验证
Posted
技术标签:
【中文标题】具有多个域和子域的 PHP 身份验证【英文标题】:PHP authentication with multiple domains and subdomains 【发布时间】:2011-05-04 17:59:21 【问题描述】:我有一个主域:main.com
,子域:test1.main.com
、test2.main.com
和其他域one.com
、two.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.com
、test2.main.com
。
我需要以某种方式保存会话以及其他域one.com
、two.com
。
如何最好地进行安全认证,如果有解决方案,我真的很困惑,请举例说明。
【问题讨论】:
我们需要方式更多关于您想要完成的任务的详细信息。身份验证与不同的域有什么关系?请编辑您的问题以添加更多细节。 ***.com/questions/244008/… 的副本 哇!永远不要将密码存储在 cookie 或数据库表中。密码应由 PHPass 库散列存储。 我已经在另一个地方更正了这个问题 此处提出的 Ajax/JS 和 iframe 解决方案:***.com/q/4813498/1066234 也可在此处查看此示例:github.com/0k/multidomain-sso 【参考方案1】:要让您的会话跨越多个域,您需要使用session_set_cookie_params()。有了它,您可以指定您的域。比如……
session_set_cookie_params(10000, "/", ".main.com");
这会将站点根目录下的所有文档以及 main.com 的所有子域的会话超时设置为 10,000 秒。
您应该先致电session_set_cookie_params()
,然后再致电session_start()
。
【讨论】:
我也这样做了 ini_set("session.cookie_domain", ".main.com");但其他域(one.com、two.com)中的问题不是子域。 啊,我明白了。为此,您将不得不手动传递会话 ID,并且可能将此会话信息存储在某处。您不能在一个域上创建 cookie 并由另一个域读取。【参考方案2】:据我所知,子域之间的跨会话很好,但它不会延续到一个全新的域。为此,您需要某种集中式数据方法或 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 有很好的理解,所以我相信你会成功的!
祝你好运。
【讨论】:
Sweet... 如果您有任何其他问题,请在此处发表评论,我也有兴趣让它发挥作用。据我所知,第三方网站(完全不同的域)上的 Facebook 身份验证使用类似的 API 令牌方法。 同意,但建议 OP 找到现有的解决方案,而不是自己动手。众所周知,“我的第一个安全系统”容易受到攻击。 请告诉我现有的解决方案 真的可以t understand how to recieve my sessid or cookie or something from main domain. i tried send sessid on logining with img to all domains but i have so many domains, i can
t明白
到目前为止,我还不知道现有的解决方案。我倾向于自己进行繁重的 PHP 编码,从头开始。我讨厌 Joomla/Drupal 等。为了安全起见,请使用您的常识 - 使用 mysql_real_escape_string() 函数防止 sql 注入,确保数据库上的令牌每 10 分钟左右自动过期,除非用户处于活动状态,在这种情况下在每次页面加载时,将令牌从当前活动状态再更新 10 分钟。确保令牌没有发送到任何电子邮件等,并且可能在每次从站点跳转到另一个站点时重新设置令牌哈希......并且不要忘记 md5() 命令!【参考方案3】:
但是如果用户直接访问域one.com,则one.com无法通过上面提到的正确答案知道用户是否登录,似乎必须使用一些额外的js,它是jsonP!我们让account.main.com/userLoginStat.php?callback=loginThisDomain来检查用户是否登录过main.com,如果有,js回调函数loginThisDomain做一些事情将用户自动登录到 one.com。
【讨论】:
以上是关于具有多个域和子域的 PHP 身份验证的主要内容,如果未能解决你的问题,请参考以下文章
向具有不同域和基本身份验证的服务器发出 ajax POST 请求是不可能的吗?