获取当前域名

我在服务器 http://www.myserver.uk.com上有我的网站。

在这台服务器上,我有两个域:

one.com and two.com

我想得到当前的域使用 PHP,但如果我使用 $_SERVER['HTTP_HOST'],然后它显示我

myserver.uk.com

而不是:

one.com or two.com

我怎样才能得到域,而不是服务器名称?

454773 次浏览

试试 $_SERVER['SERVER_NAME']

提示: 创建一个调用函数 phpinfo()的 PHP 文件,查看“ PHP 变量”部分。有很多有用的变量我们从没想过。

试着用这个:

$_SERVER['SERVER_NAME']

或者解析:

$_SERVER['REQUEST_URI']

参考资料: Apache _ request _ headers ()

使用 $_SERVER['HTTP_HOST']可以获得(子域.) maindomain.ext.It 似乎是我认为最简单的解决方案。

如果您实际上是通过 iFrame 进行“重定向”,那么您可以添加一个 走开参数来表示域。

<iframe src="myserver.uk.com?domain=one.com"/>

然后,您可以设置一个会话变量,在整个应用程序中持久存储这些数据。

最好的办法就是

echo $_SERVER['HTTP_HOST'];

它可以这样使用:

if (strpos($_SERVER['HTTP_HOST'], 'banana.com') !== false) {
echo "Yes this is indeed the banana.com domain";
}

下面的代码是在结构化 HTML 输出中查看 $_ SERVER 中所有变量的好方法,其中突出显示了执行后直接停止的关键字。因为我有时会忘记用哪一个——我认为这个可以很漂亮。

<?php
// Change banana.com to the domain you were looking for..
$wordToHighlight = "banana.com";
$serverVarHighlighted = str_replace( $wordToHighlight, '<span style=\'background-color:#883399; color: #FFFFFF;\'>'. $wordToHighlight .'</span>',  $_SERVER );
echo "<pre>";
print_r($serverVarHighlighted);
echo "</pre>";
exit();
?>

我知道这可能不完全是这个主题,但是根据我的经验,我发现将当前 URL 的 WWW-ness 存储在一个变量中是很有用的。

此外,请看下面我的评论,看看这是什么意思。

在决定是否使用“ www”发送 Ajax 调用时,这一点很重要:

$.ajax("url" : "www.site.com/script.php", ...


$.ajax("url" : "site.com/script.php", ...

当发送一个 Ajax 调用时,域名必须与浏览器地址栏中的域名相匹配,否则控制台中将有一个 未捕获的安全错误

所以我想出了解决这个问题的办法:

<?php
substr($_SERVER['SERVER_NAME'], 0, 3) == "www" ? $WWW = true : $WWW = false;


if ($WWW) {
/* We have www.example.com */
} else {
/* We have example.com */
}
?>

然后,根据 $WWW 是真还是假,运行适当的 Ajax 调用。

我知道这可能听起来微不足道,但这是一个很容易被绊倒的常见问题。

这是唯一安全的办法

检索当前域的唯一保证安全的方法是自己将其存储在一个安全的位置。

大多数框架负责为您存储域,因此您需要查阅特定框架的文档。如果您没有使用框架,可以考虑将域存储在下列位置之一:

存储域的安全方法 使用者
配置文件 乔姆拉(Joomla) ,美国广播公司(Drupal)
数据库 WordPress
一个环境变量 Laravel
服务注册表 Kubernetes DNS

下面的工作... 但他们不安全

黑客可以让以下变量输出他们想要的任何域。这可能导致缓存中毒和几乎不可察觉的网络钓鱼攻击。

$_SERVER['HTTP_HOST']

这会从 容易被黑客操纵的请求头中获取域。与:

$_SERVER['SERVER_NAME']

如果关闭 Apache 设置 使用经典名称,则可以更好地实现这一点; 在这种情况下,将不再允许使用任意值填充 $_SERVER['SERVER_NAME'],而且 $_SERVER['SERVER_NAME']是安全的。但是,这是非默认的,并且不是常见的设置。

在流行系统中

下面是如何在以下框架/系统中获得当前域名:

WordPress

$urlparts = parse_url(home_url());
$domain = $urlparts['host'];

如果你在 WordPress 中构建一个 URL,只需使用 主页或者 Site _ url,或者任何一个 其他网址功能

Laravel

request()->getHost()

request()->getHost功能继承自 Symfony,自2013年 CVE-2013-4752打补丁以来一直是安全的。

Drupal

安装程序还没有处理这个安全问题(第2404259期)。但是在 Drupal 8中有一些文档,你可以在 可信主机设置中使用它们来保护你的 Drupal 安装,之后可以使用以下内容:

\Drupal::request()->getHost();

其他框架

请随意编辑此答案,以包括如何获得您喜欢的框架中的当前域。当这样做的时候,请包括一个链接到相关的源代码或任何其他可以帮助我验证框架正在安全地做事情的链接。


附录

剥削的例子:

  1. 如果僵尸网络持续使用错误的主机头请求页面,则可能发生缓存中毒。生成的 HTML 将包含到攻击者网站的链接,在那里他们可以钓鱼你的用户。起初,恶意链接只会发送回黑客,但如果黑客做了足够的请求,恶意版本的网页将最终在您的缓存中,它将分发给其他用户。

  2. 如果根据主机头在数据库中存储链接,就可能发生钓鱼攻击。例如,假设您在论坛上存储用户配置文件的绝对 URL。通过使用错误的标题,黑客可以得到任何人谁点击他们的配置文件链接发送钓鱼网站。

  3. 如果黑客在为其他用户填写密码重置表单时使用恶意主机头,则可能发生密码重置中毒。然后,该用户将收到一封包含密码重置链接的电子邮件,该链接将导致钓鱼网站。另一种更复杂的形式是跳过用户必须做的任何事情,让电子邮件跳转并重新发送到黑客的 SMTP 服务器之一 < a href = “ https://cve.mitre.org/cgi-bin/cvename.cgi? name = CVE-2017-8295”rel = “ nofollow noReferrer”> (例如 CVE-2017-8295)

  4. 这里有一些更恶意的例子

附加警告和注意事项:

  • 使用经典名称被关闭时,$_SERVER['SERVER_NAME']被填充为 $_SERVER['HTTP_HOST']无论如何都会使用的相同头(加上端口)。这是 Apache 的默认设置。如果您或 DevOps 打开了这个功能,那么您就没问题了——差不多——但是您真的想要依靠一个独立的团队,或者三年后的您自己,来保持一个看起来像是小配置的非默认值吗?尽管这样可以保证安全性,但是我还是要提醒大家不要依赖于这个设置。
  • 但是,Red Hat 在默认情况下确实打开了 useconical [ 来源]。
  • 如果在虚拟主机条目中使用了 服务器别名,并且请求了别名域,则 $_SERVER['SERVER_NAME']将不返回当前域,而是返回 serverName 指令的值。
  • 如果无法解析 serverName,则在其位置使用操作系统的 hostname 命令 [来源]
  • 如果忽略主机头,则服务器的行为将与 useconical 类似 在 [来源]台。
  • 最后,我只是尝试在我的本地服务器上利用这一点,但是无法欺骗主机头。我不确定 Apache 是否有更新来解决这个问题,或者我只是做错了什么。无论如何,在不使用虚拟主机的环境中,这个头仍然是可利用的。

A Little Rant:

这个问题收到了成千上万的观点,却没有一个提到手头的安全问题!它不应该是这样的,但是仅仅因为 Stack Overflow 答案是流行的,并不意味着它是安全的。



每个人都在使用 parse_url函数,但有时用户可能以不同的格式传递参数。

为了解决这个问题,我创建了一个函数,看看这个:

function fixDomainName($url='')
{
$strToLower = strtolower(trim($url));
$httpPregReplace = preg_replace('/^http:\/\//i', '', $strToLower);
$httpsPregReplace = preg_replace('/^https:\/\//i', '', $httpPregReplace);
$wwwPregReplace = preg_replace('/^www\./i', '', $httpsPregReplace);
$explodeToArray = explode('/', $wwwPregReplace);
$finalDomainName = trim($explodeToArray[0]);
return $finalDomainName;
}

只需传递 URL 并获得域名。

比如说,

echo fixDomainName('https://stackoverflow.com');

将返回:

stackoverflow.com

在某些情况下:

echo fixDomainName('stackoverflow.com/questions/id/slug');

它也会返回 stackoverflow.com

获取域名:

$_SERVER['HTTP_HOST']

域名与协议:

$protocol = strpos(strtolower($_SERVER['SERVER_PROTOCOL']), 'https') === FALSE ? 'http' : 'https';
$domainLink = $protocol . '://' . $_SERVER['HTTP_HOST'];

Protocol,domain,and queryString 合计:

$url = $protocol . '://' . $_SERVER['HTTP_HOST'] . '?' . $_SERVER['QUERY_STRING'];

由于 $_ SERVER [‘ SERVER _ NAME’]对于多域主机来说是不可靠的!