Jaka jest różnica między PHP HTTP_HOST
a SERVER_NAME
PHP?
gdzie:
HTTP_POST
===$_SERVER['HTTP_HOST']
SERVER_NAME
===$_SERVER['SERVER_NAME']
Kiedy rozważasz użycie jednego nad drugim i dlaczego?
php
apache
server-variables
Emanuil Rusev
źródło
źródło
HTTP_HOST
. W przeciwnym razie osoba atakująca może wprowadzić dowolną wartość wHost:
żądaniu HTTP i zmusić serwer do jej zaakceptowania.$_SERVER['HTTP_HOST']
lub$_SERVER['SERVER_NAME']
Odpowiedzi:
HTTP_HOST
Jest otrzymywany z nagłówka żądania HTTP i to, co klient faktycznie wykorzystywane jako „host docelowy” wniosku.SERVER_NAME
Jest zdefiniowany w konfiguracji serwera. To, którego użyć, zależy od tego, do czego go potrzebujesz. Powinieneś jednak teraz zdać sobie sprawę, że jedna jest wartością kontrolowaną przez klienta, która może dlatego nie być wiarygodna do zastosowania w logice biznesowej, a druga jest wartością kontrolowaną przez serwer, która jest bardziej niezawodna. Musisz jednak upewnić się, że dany serwer WWW maSERVER_NAME
poprawnie skonfigurowany. Biorąc przykład Apache HTTPD, oto fragment jego dokumentacji :Aktualizacja : po sprawdzeniu odpowiedzi Pekki na twoje pytanie, która zawiera link do odpowiedzi bobince'a, za którą PHP zawsze zwróci
HTTP_HOST
wartośćSERVER_NAME
, co jest sprzeczne z moimi własnymi doświadczeniami PHP 4.x + Apache HTTPD 1.2.x sprzed kilku lat , Zdmuchnąłem trochę kurzu z mojego obecnego środowiska XAMPP w systemie Windows XP (Apache HTTPD 2.2.1 z PHP 5.2.8), uruchomiłem go, utworzyłem stronę PHP, która drukuje obie wartości, stworzyłem aplikację testową JavaURLConnection
do modyfikacjiHost
nagłówka i testy nauczyły mnie, że tak jest rzeczywiście (niepoprawnie).Po pierwszym podejrzeniu PHP i przejrzeniu niektórych raportów o błędach PHP dotyczących tego tematu, dowiedziałem się, że źródłem problemu jest używany serwer sieciowy i że niepoprawnie zwrócił
Host
nagłówek HTTP, gdySERVER_NAME
został o to poproszony. Więc zagłębiłem się w raporty błędów Apache HTTPD przy użyciu różnych słów kluczowych dotyczących tematu i w końcu znalazłem pokrewny błąd . To zachowanie zostało wprowadzone od około Apache HTTPD 1.3. Trzeba ustawićUseCanonicalName
dyrektywyon
w<VirtualHost>
wpisuServerName
INhttpd.conf
(również sprawdzić ostrzeżenia na dole dokumentu !).To zadziałało dla mnie.
Podsumowując,
SERVER_NAME
jest bardziej niezawodny, ale jesteś zależny od konfiguracji serwera!źródło
server_name
dyrektywę. Zwłaszcza jeśli nieserver_name
jest ustawione, również_SERVER["SERVER_NAME"]
będzie puste.HTTP_HOST
to host docelowy wysłany przez klienta. Użytkownik może nim dowolnie manipulować. Nie ma problemu z wysłaniem żądania do Twojej witryny z prośbą oHTTP_HOST
wartośćwww.stackoverflow.com
.SERVER_NAME
pochodzi zVirtualHost
definicji serwera i dlatego jest uważany za bardziej niezawodny. Można jednak nim również manipulować z zewnątrz pod pewnymi warunkami związanymi z konfiguracją serwera WWW: zobacz To pytanie SO, które dotyczy aspektów bezpieczeństwa obu odmian.Nie powinieneś polegać na żadnym z nich, aby być bezpiecznym. To powiedziawszy, to, czego użyć naprawdę zależy od tego, co chcesz zrobić. Jeśli chcesz ustalić, na której domenie działa skrypt, możesz bezpiecznie korzystać,
HTTP_HOST
dopóki niepoprawne wartości pochodzące od złośliwego użytkownika nie mogą niczego zepsuć.źródło
UseCanonicalName on
w httpd.conf, aby wymusićSERVER_NAME
rzeczywistą nazwę serwera.$_SERVER['SERVER_NAME']
nie działałby również . Źle skonfigurowany serwer ustawi się$_SERVER['SERVER_NAME']
na podstawie wartościHost:
żądania klienta . Oba są równe.Jak wspomniałem w tej odpowiedzi , jeśli serwer działa na porcie innym niż 80 (co może być powszechne na komputerze deweloperskim / intranetowym), wówczas
HTTP_HOST
zawiera port, podczas gdySERVER_NAME
nie.(Przynajmniej tak zauważyłem w wirtualnych hostach opartych na portach Apache)
Należy pamiętać, że
HTTP_HOST
ma nie zawierać:443
, gdy działa na HTTPS (chyba że działa na niestandardowym porcie, które nie zostały przetestowane).Jak zauważyli inni, oba różnią się także przy korzystaniu z IPv6:
źródło
Pamiętaj, że jeśli chcesz korzystać z IPv6, prawdopodobnie
HTTP_HOST
raczej chcesz go używaćSERVER_NAME
. Jeśli wpiszeszhttp://[::1]/
zmienne środowiskowe, będą to:Oznacza to, że jeśli wykonasz mod_rewrite, możesz uzyskać nieprzyjemny wynik. Przykład przekierowania SSL:
Dotyczy to TYLKO jeśli uzyskasz dostęp do serwera bez nazwy hosta.
źródło
https://%{SERVER_NAME}%{REQUEST_URI}
Jeśli chcesz sprawdzić przez server.php lub cokolwiek innego, chcesz wywołać go w następujący sposób:
lub
Następnie uzyskaj dostęp do wszystkich prawidłowych adresów URL swojej witryny i sprawdź różnicę.
źródło
Zależy, co chcę się dowiedzieć. SERVER_NAME to nazwa hosta serwera, podczas gdy HTTP_HOST to wirtualny host, z którym klient się łączy.
źródło
SERVER_NAME
to zwykle nazwa VirtualHost, a nie sam serwer. A w ApacheSERVER_NAME
jest często zapełniany tą samą wartością coHTTP_HOST
(patrz odpowiedź BalusC).SERVER_NAME
dotyczy to wirtualnego hosta. Jednak nadal można użyć konfiguracji hosta wirtualnego dla jednej witryny. Wiele osób korzysta z hostingu współdzielonego, więc rozumiem twój punkt widzenia.Trochę czasu zajęło mi zrozumienie, co ludzie rozumieją przez „
SERVER_NAME
jest bardziej niezawodny”. Używam serwera współdzielonego i nie mam dostępu do dyrektyw hosta wirtualnego. Tak więc używam mod_rewrite w.htaccess
do mapowania różnychHTTP_HOST
s do różnych katalogów. W takim przypadku maHTTP_HOST
to sens.Sytuacja jest podobna, jeśli używa się hostów wirtualnych opartych na nazwach:
ServerName
dyrektywa w hoście wirtualnym mówi po prostu, która nazwa hosta zostanie zmapowana na tym hoście wirtualnym. Najważniejsze jest to, że w obu przypadkachHTTP_HOST
nazwa hosta podana przez klienta podczas request ( ) musi być dopasowana do nazwy na serwerze, która sama jest odwzorowana na katalog. Niezależnie od tego, czy mapowanie odbywa się za pomocą dyrektyw hosta wirtualnego, czy za pomocą htaccess, reguły mod_rewrite mają tutaj znaczenie wtórne. W takich przypadkachHTTP_HOST
będzie taki sam jakSERVER_NAME
. Cieszę się, że Apache jest skonfigurowany w ten sposób.Sytuacja wygląda jednak inaczej w przypadku hostów wirtualnych opartych na protokole IP. W takim przypadku i tylko w tym przypadku,
SERVER_NAME
aHTTP_HOST
może być inaczej, bo teraz klient wybiera serwer przez IP, a nie nazwy. Rzeczywiście mogą istnieć specjalne konfiguracje, w których jest to ważne.Tak więc, od teraz, użyję
SERVER_NAME
, na wypadek, gdyby mój kod został przeniesiony w tych specjalnych konfiguracjach.źródło
Zakładając, że masz prostą konfigurację (CentOS 7, Apache 2.4.x i PHP 5.6.20) i tylko jedną stronę internetową (nie zakładając wirtualnego hostingu) ...
W sensie PHP
$_SERVER['SERVER_NAME']
jest elementem, który PHP rejestruje w$_SERVER
superglobalu na podstawie konfiguracji Apache (**ServerName**
dyrektywy zUseCanonicalName On
) w httpd.conf (czy to z dołączonego pliku konfiguracji hosta wirtualnego, cokolwiek, itp.). HTTP_HOST pochodzi zhost
nagłówka HTTP . Traktuj to jako dane wprowadzone przez użytkownika. Filtruj i sprawdzaj przed użyciem.Oto przykład, w którym wykorzystuję
$_SERVER['SERVER_NAME']
jako podstawę porównania. Poniższa metoda pochodzi z konkretnej klasy potomnej, którą nazwałemServerValidator
(child ofValidator
).ServerValidator
sprawdza sześć lub siedem elementów w $ _SERVER przed ich użyciem.Przy określaniu, czy żądanie HTTP jest POST, używam tej metody.
Do czasu wywołania tej metody nastąpiłoby całe filtrowanie i sprawdzanie poprawności odpowiednich elementów $ _SERVER (i odpowiednich właściwości).
Linia ...
... sprawdza, czy
$_SERVER['HTTP_HOST']
wartość (ostatecznie uzyskana z żądanegohost
nagłówka HTTP) jest zgodna$_SERVER['SERVER_NAME']
.Teraz używam superglobalną mówić wyjaśnić moim przykładem, ale to tylko dlatego, że niektórzy ludzie nie znają
INPUT_GET
,INPUT_POST
orazINPUT_SERVER
w odniesieniu dofilter_input_array()
.Najważniejsze jest to, że nie obsługuję żądań POST na moim serwerze, chyba że zostaną spełnione wszystkie cztery warunki. W związku z tym, jeśli chodzi o żądania POST, brak dostarczenia
host
nagłówka HTTP (przetestowanego pod kątem obecności wcześniej) oznacza zgubę dla ścisłych przeglądarek HTTP 1.0 . Ponadto zwróciła gospodarz musi odpowiadać wartości dlaServerName
w httpd.conf , a za przedłużeniem, wartość$_SERVER('SERVER_NAME')
w$_SERVER
superglobalną. Znowu używałbymINPUT_SERVER
z funkcjami filtrowania PHP, ale łapiesz mój dryf.Należy pamiętać, że Apache często używa
ServerName
się standardowych przekierowań (takie jak pozostawiając ukośnik off URL: przykład http://www.foo.com staje http://www.foo.com/ ), nawet jeśli nie są za pomocą przepisywania adresów URL.Używam
$_SERVER['SERVER_NAME']
jako standardu, nie$_SERVER['HTTP_HOST']
. W tej kwestii jest wiele do przodu i do tyłu.$_SERVER['HTTP_HOST']
może być pusty, więc nie powinno to stanowić podstawy do tworzenia konwencji kodu, takich jak powyższa metoda publiczna. Ale tylko dlatego, że oba mogą być ustawione, nie gwarantuje, że będą równe. Testowanie jest najlepszym sposobem, aby wiedzieć na pewno (mając na uwadze wersję Apache i wersję PHP).źródło
Jak powiedział balusC, SERVER_NAME nie jest niezawodny i można go zmienić w konfiguracji apache, konfiguracji nazwy serwera i zaporze ogniowej, która może znajdować się między tobą a serwerem.
Następująca funkcja zawsze zwraca prawdziwy host (host wpisany przez użytkownika) bez portu i jest prawie niezawodny:
źródło
$ _SERVER [„SERVER_NAME”] jest oparty na konfiguracji serwerów internetowych. $ _SERVER ['HTTP_HOST'] jest oparty na żądaniu klienta.
źródło