Получить текущий домен

143

У меня на сервере есть свой сайт http://www.myserver.uk.com.

На этом сервере у меня два домена:

one.com and two.com

Я хотел бы получить текущий домен с помощью PHP, но если я использую, $_SERVER['HTTP_HOST']он показывает мне

 myserver.uk.com

вместо того:

one.com or two.com

Как мне получить домен, а не имя сервера?

Тони Эвайт
источник
Вы можете получить только первичный URl. Какой из этих трех является Первоначальным?
Code Spy
2
Как именно ваши два домена «перенаправляют» запросы на ваш сервер?
xiaofeng.li
1
@infgeoax, вероятно, фрейм ...
CodeCaster
основной - myserver.uk.com. так как я могу получить текущее доменное имя? Если я открою сайт с адресом one.com, я бы хотел получить one.com вместо myserver.uk.com
Тони Эвайт
@TonyEvyght, вот что я пытаюсь донести до infgeoax, вы должны получить имя хоста, с которым вы подключаетесь $_SERVER['HTTP_HOST']. Если сайты one.comи two.com«перенаправляют» с помощью (i) фрейма, сама страница по-прежнему поступает с myserver.uk.com, поэтому вы не получите реальный домен. Для чего нужен источник HTML one.com?
CodeCaster

Ответы:

177

Попробуйте использовать это: $_SERVER['SERVER_NAME']

Или разобрать

$_SERVER['REQUEST_URI']

apache_request_headers ()

одна половина
источник
23
-1: Только с этим ответом я точно не знаю, что делают разные предложения, на которые я смотрю. Конечно, это дает мне повод продолжать поиски, но сам по себе это не лучший ответ ...
Джаспер
4
просто print_r (apache_request_headers ()) и вы все поймете :)
половина
2
@SarahLewis HTTP_X_ORIGINAL_HOSTможет быть изменен пользователем, и ему нельзя доверять. Это не всегда может быть проблемой, но об этом следует знать.
wp-overwatch.com
67

Лучшее использование было бы

echo $_SERVER['HTTP_HOST'];

И его можно использовать так:

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

Приведенный ниже код - хороший способ увидеть все переменные в $ _SERVER в структурированном HTML-выводе с выделенными ключевыми словами, которые останавливаются сразу после выполнения. Поскольку я иногда забываю, какой из них использовать, думаю, это может быть здорово.

<?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']получает меня (поддомен.) Maindomain.extension. Мне это кажется самым простым решением.

Если вы на самом деле «перенаправляете» через iFrame, вы можете добавить параметр GET, который указывает домен.

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

А затем вы можете установить переменную сеанса, которая сохраняет эти данные во всем вашем приложении.

Raz0rwire
источник
1
наиболее важно, что он включает номер порта, так что мне не нужно потом объединять его. Однако phpinfo, предложенный bsdnoobz, помогает мне найти правильное решение.
35

Единственный безопасный способ сделать это

Все остальные ответы на этой странице имеют последствия для безопасности, о которых вам нужно знать. Единственный гарантированно безопасный метод получения текущего домена - это самому сохранить его в безопасном месте .

Большинство фреймворков заботятся о хранении домена за вас, поэтому вы захотите ознакомиться с документацией для вашего конкретного фреймворка. Если вы не используете фреймворк, рассмотрите возможность хранения домена в одном из следующих мест:

+ ------------------------------------------------- --- + ----------------------------------- +
 | Безопасные методы хранения домена | Используется |
+ ------------------------------------------------- --- + ----------------------------------- +
 | Файл конфигурации | 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'];

Если вы создаете URL-адрес в WordPress, просто используйте home_url или site_url или любую другую функцию URL .

Laravel

request()->getHost()

Эта request()->getHostфункция унаследована от Symfony и является безопасной с момента исправления CVE-2013-4752 2013 года .

Drupal

Программа установки еще не позаботилась об обеспечении безопасности ( проблема № 2404259 ). Но в Drupal 8 есть документация, за которой вы можете следить в настройках доверенного хоста, чтобы защитить вашу установку Drupal, после чего можно использовать следующее:

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

Другие фреймворки

Не стесняйтесь редактировать этот ответ, чтобы указать, как получить текущий домен в вашей любимой структуре. При этом включите ссылку на соответствующий исходный код или на что-нибудь еще, что поможет мне убедиться, что фреймворк работает безопасно.


Дополнение

Примеры эксплуатации:

  1. Отравление кеша может произойти, если ботнет постоянно запрашивает страницу с использованием неправильного заголовка хоста. В результате полученный HTML-код будет включать ссылки на веб-сайт злоумышленников, где они могут фишинговать ваших пользователей. Сначала вредоносные ссылки будут отправлены обратно только хакеру, но если хакер сделает достаточно запросов, вредоносная версия страницы окажется в вашем кеше, где она будет распространена среди других пользователей.

  2. Фишинговая атака может произойти, если вы храните ссылки в базе данных на основе заголовка hosts. Например, допустим, вы храните абсолютный URL-адрес профилей пользователя на форуме. Используя неправильный заголовок, хакер может заставить любого, кто нажимает на ссылку своего профиля, отправить на фишинговый сайт.

  3. Отравление для сброса пароля может произойти, если хакер использует заголовок вредоносных хостов при заполнении формы сброса пароля для другого пользователя. Затем этот пользователь получит электронное письмо со ссылкой для сброса пароля, ведущей на фишинговый сайт.

  4. Вот еще несколько вредоносных примеров

Дополнительные предостережения и примечания:

  • Когда usecanonicalname отключен, $_SERVER['SERVER_NAME']он заполняется тем же заголовком, $_SERVER['HTTP_HOST']который использовался бы в любом случае (плюс порт). Это настройка Apache по умолчанию. Если вы или DevOps включите это, то с вами все в порядке, но действительно ли вы хотите полагаться на отдельную команду или на себя через три года в будущем, чтобы сохранить то, что может показаться второстепенной конфигурацией. -значение по умолчанию? Несмотря на то, что это обеспечивает безопасность, я бы не стал полагаться на эту установку.
  • Redhat, однако, по умолчанию включает usecanonical [ источник ].
  • Если serverAlias используется в записи виртуальных хостов и запрашивается домен с псевдонимом, $_SERVER['SERVER_NAME']не будет возвращен текущий домен, но будет возвращено значение директивы serverName.
  • Если serverName не может быть разрешен, вместо него используется команда hostname операционной системы [источник] .
  • Если не указать заголовок хоста, сервер будет вести себя так, как если бы usecanonical был на [источник] .
  • Наконец, я просто попытался использовать это на своем локальном сервере и не смог подделать заголовок хоста. Я не уверен, было ли обновление Apache для решения этой проблемы, или я просто делал что-то не так. Тем не менее, этот заголовок по-прежнему может использоваться в средах, где виртуальные хосты не используются.

Маленький Рент:

     Этот вопрос получил сотни тысяч просмотров без единого упоминания о существующих проблемах безопасности! Так быть не должно, но то, что ответ на вопрос о переполнении стека популярен, не означает, что он безопасен.



wp-overwatch.com
источник
1
Возможно, вы захотите упомянуть разницу между home_url и site_url. wordpress.stackexchange.com/a/50605/13
Volomike 08
1
+1 для пользователей wordpress. Хорошо, если вам нужно проверить, установлен ли он в подкаталоге, но обратите внимание, что ключ parse_url: $urlparts['path']не установлен, если он установлен в корневом каталоге домена. Else $urlparts['path']возвращает подкаталог.
Йонас Лундман
9

Попробуй $_SERVER['SERVER_NAME'].

Советы: Создайте файл PHP, который вызывает функцию, phpinfo()и просмотрите раздел «Переменные PHP». Есть множество полезных переменных, о которых мы никогда не думаем.

свободный от потока
источник
вы всегда можете попробовать print_r-ing the $ _SERVER и
3

Я знаю, что это может быть не совсем по теме, но, по моему опыту, я считаю полезным сохранение WWW-статуса текущего URL-адреса в переменной.

Изменить: Кроме того, посмотрите мой комментарий ниже, чтобы узнать, к чему это идет.

Это важно при определении того, следует ли отправлять вызовы Ajax с www или без:

$.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 или ложно, запустите правильный вызов Ajax.

Я знаю, что это может показаться тривиальным, но это настолько распространенная проблема, о которой легко споткнуться.

Бесконечный стек
источник
OP явно запросил домен, а не SERVER_NAME .
Себастьян Маринеску
Верно, но в наши дни вы должны беспокоиться и о проблеме с www.
InfiniteStack
Зачем? В JS вы можете заглянуть window.location. В PHP у вас есть SERVER_NAME.
Себастьян Маринеску
4
SERVER_NAME возвращает "www.site.com", даже если "site.com" введено в адресную строку. Если вы используете SERVER_NAME во всем своем коде, вы неизбежно столкнетесь с проблемой безопасности www / no-www, особенно когда дело доходит до вызовов Ajax. Но чтобы ответить на ваш вопрос, при продвинутом программировании PHP иногда требуется динамически генерировать код, который выполняет HTTP-вызов на сервер. Если целевой URL-адрес содержит «www» на странице, на которой его нет, это вызовет ошибку безопасности.
InfiniteStack
Ладно ладно ... Я читал об этом, и вы правы. Так что ваш ответ может быть кому-то актуален. Хорошая работа :)
Себастьян Маринеску
3

Все используют эту 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.

Manojkiran.A
источник
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];
Движение
источник