获取当前域


140

我的网站在服务器上

http://www.myserver.uk.com

为此,我有两个域,

http://one.com

http://two.com

我想使用PHP当前域,但是如果我使用,$_SERVER['HTTP_HOST']则可以告诉我

myserver.uk.com

代替:

one.com or two.com

如何获取域而不是服务器名称?

我有PHP版本5.2。


您只能获得主URl。这三者中哪一个是小学?
Code Spy

2
您的两个域究竟如何将请求“重定向”到您的服务器?
xiaofeng.li 2012年

1
@infgeoax可能是一个框架...
CodeCaster

主要是myserver.uk.com。那么我如何获得当前域名?如果我打开地址为
one.com的

@TonyEvyght正是infgeoax的关键所在,我试图做到这一点,您应该在中获得与之连接的主机名$_SERVER['HTTP_HOST']。如果这些站点one.com和站点two.com正在使用(i)框架“重定向”,则页面本身仍来自myserver.uk.com,因此您将无法获得真实域。HTML的来源是one.com什么?
CodeCaster

Answers:


175

尝试使用此: $_SERVER['SERVER_NAME']

或解析

$_SERVER['REQUEST_URI']

apache_request_headers()


23
-1:仅凭此答案,我不完全知道我在寻找不同的建议。当然,这给了我一点要继续寻找的观点,但是就其本身而言,这确实不是一个很好的答案……
Jasper 2015年

4
只需print_r(apache_request_headers()),您就会了解所有的内容:)
2015年

2
@SarahLewis HTTP_X_ORIGINAL_HOST可以被用户修改,并且不能被信任。这可能并不总是一个问题,但需要注意。
wp-overwatch.com

64

最好的用途是

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();
?>

39

使用$_SERVER['HTTP_HOST']可以获取(subdomain。)maindomain.extension。对我来说,这似乎是最简单的解决方案。

如果您实际上是通过iFrame进行“重定向”,则可以添加一个说明域的GET参数。

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

然后,您可以设置一个会话变量,以在整个应用程序中保留此数据。


1
最重要的是,它包括端口号,这样以后就不需要再连接了。bsdnoobz建议的phpinfo可以帮助我找到正确的解决方案。

30

唯一安全的方法

此页面上的所有其他答案都具有安全隐患,您需要注意这些隐患。

检索当前域的唯一有保证的安全方法 是𝓼𝓽𝓸𝓻𝓮𝓲𝓽𝓪𝔂𝓸𝓾𝓻𝓼𝓮𝓵𝓯。

大多数框架都会为您存储域,因此您将需要查阅特定框架的文档。如果不使用框架,请考虑将域存储在以下位置之一:

+ ------------------------------------------------- --- + ----------------------------------- +
 | 存储域的安全方法| 使用者|
+ ------------------------------------------------- --- + ----------------------------------- +
 | 配置文件| Joomla,Drupal / Symfony |
 | 数据库| WordPress |
 | 环境变量| Laravel |
 | 服务注册表| Kubernetes DNS |
+ ------------------------------------------------- --- + ----------------------------------- +


您可以使用以下内容...但是它们不安全

黑客可以使这些变量输出所需的任何域。这可能导致缓存中毒和几乎没有注意到的网络钓鱼攻击。

$_SERVER['HTTP_HOST']

这是从请求标头获取域的,请求标头可以被黑客操纵。与:

$_SERVER['SERVER_NAME']

如果关闭Apache设置usecanonicalname,可以使这一方法更好。在这种情况下,$_SERVER['SERVER_NAME']将不再允许使用任意值进行填充,并且这种方法是安全的。但是,这不是默认设置,在设置中并不常见。


在流行的系统中

以下是如何在以下框架/系统中获得当前域的方法:

WordPress的

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

如果要在WordPress中构造URL,则只需使用home_urlsite_url或任何其他URL函数

拉拉韦尔

request()->getHost()

request()->getHost功能继承自Symfony,自对2013 CVE-2013-4752进行修补以来一直安全。

Drupal

安装程序尚未确保此安全(发行#2404259)。但是在Drupal 8中有文档,您可以在Trusted Host Settings中遵循这些文档来保护您的Drupal安装,之后可以使用以下内容:

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

其他框架

随意编辑此答案以包括如何在您喜欢的框架中获取当前域。这样做时,请提供指向相关源代码或其他任何链接的链接,这些链接将帮助我验证框架是否在安全地执行操作。




附录

开发示例:

  1. 如果僵尸网络不断使用错误的主机头请求页面,则会发生缓存中毒。然后,生成的HTML将包含指向攻击者网站的链接,攻击者可以在其中诱骗您的用户。最初,恶意链接只会发送回给黑客,但是,如果黑客发出了足够的请求,则该页面的恶意版本将最终出现在您的缓存中,并将其分发给其他用户。

  2. 如果您基于主机头将链接存储在数据库中,则可能会发生网络钓鱼攻击。例如,假设您将绝对URL存储到论坛上用户的个人资料中。通过使用错误的标头,黑客可以使单击其个人资料链接的任何人都被发送到钓鱼网站。

  3. 如果黑客在为其他用户填写密码重置表单时使用恶意主机头,则会发生密码重置中毒。然后,该用户将收到一封电子邮件,其中包含通向钓鱼网站的密码重置链接。

  4. 这是一些恶意示例

其他注意事项和注意事项:

  • 关闭usecanonicalname时,无论如何都将$_SERVER['SERVER_NAME']使用相同的标头填充该标头$_SERVER['HTTP_HOST'](加上端口)。这是Apache的默认设置。如果您或开发人员启用了此功能,那么您会没事-ish-但您是否真的想依靠一个单独的团队,或者自己未来三年,以保持看起来像是次要的配置? -默认值?即使这样做可以确保安全,但我还是提醒不要依赖此设置。
  • 但是,Redhat确实默认情况下会启用usecanonical [ source ]。
  • 如果在虚拟主机条目中使用serverAlias,并且请求了别名域,$_SERVER['SERVER_NAME']则不会返回当前域,但会返回serverName指令的值。
  • 如果无法解析serverName,则在其位置[source]处使用操作系统的hostname命令。
  • 如果省略了主机头,则服务器将表现为useuseonical位于[source]上
  • 最后,我只是尝试在本地服务器上利用此漏洞,但无法欺骗主机头。我不确定Apache是​​否有解决此问题的更新,或者我做错了什么。无论如何,在不使用虚拟主机的环境中,仍可以利用此头。

小兰特:

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




1
您可能要提及home_url和site_url之间的区别。wordpress.stackexchange.com/a/50605/13
Volomike

1
WordPress用户+1。如果您需要检查是否安装在subdir中,则很好,但是请注意,$urlparts['path']如果安装在domain的根目录中,则未设置parse_url key:。否则$urlparts['path']返回子目录。
乔纳斯·隆德曼

9

尝试$_SERVER['SERVER_NAME']

提示:创建一个调用该函数的PHP文件,phpinfo()然后查看“ PHP变量”部分。这里有很多我们从未想到的有用变量。


您可以随时尝试在$ _SERVER中使用print_r-ing并进行搜索

3

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

编辑:另外,请参阅下面的我的评论,以了解其含义。

在确定是否使用“ www”或不使用“ www”调度Ajax调用时,这一点很重要。

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

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

调度Ajax调用时,域名必须与浏览器地址栏中的域名匹配,否则控制台中将出现Uncaught SecurityError

所以我想出了这个解决方案来解决这个问题:

<?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是true还是false来运行正确的Ajax调用。

我知道这听起来很琐碎,但这是一个常见问题,很容易被绊倒。


OP明确要求提供域,而不是SERVER_NAME
塞巴斯蒂安·G·马里内斯库

没错,但是这些天您也必须担心www问题。
InfiniteStack

为什么?在JS中,您可以查看window.location。在PHP中,您得到了SERVER_NAME
塞巴斯蒂安·马里内斯库

4
即使在地址栏中输入“ site.com”,SERVER_NAME也会返回“ www.site.com”。如果在整个代码中都使用SERVER_NAME,那么不可避免地会遇到www / no-www安全问题,尤其是在进行Ajax调用时。但是要回答您的问题,在高级PHP编程中,有时PHP需要动态生成对服务器进行HTTP调用的代码。如果目标URL在页面上未包含“ www”,则将生成安全错误。
InfiniteStack

好吧好吧...我读到了,你说得对。因此,您的答案可能与某人有关。干得好:)
塞巴斯蒂安·G·马里内斯库

3

每个人都在使用该parse_url功能,但有时用户可能会以不同的格式传递argumet。

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

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


1
$_SERVER['HTTP_HOST'] 

//获取域

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

//具有协议的域

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

//协议,域,queryString总计**由于$ _SERVER ['SERVER_NAME']对于多域托管不可靠!


-2

只需尝试:

echo apache_request_headers()[3];
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.