Was ist der Unterschied zwischen HTTP_HOST
und SERVER_NAME
in PHP?
wo:
HTTP_POST
===$_SERVER['HTTP_HOST']
SERVER_NAME
===$_SERVER['SERVER_NAME']
Wann würden Sie in Betracht ziehen, übereinander zu verwenden und warum?
php
apache
server-variables
Emanuil Rusev
quelle
quelle
HTTP_HOST
auf der Whitelist zu überprüfen . Andernfalls kann ein Angreifer einen beliebigen Wert in die HTTP-Host:
Anforderung eingeben und den Server dazu bringen, diesen zu akzeptieren.$_SERVER['HTTP_HOST']
oder$_SERVER['SERVER_NAME']
Antworten:
Das
HTTP_HOST
wird aus dem HTTP-Anforderungsheader abgerufen und dies ist, was der Client tatsächlich als "Zielhost" der Anforderung verwendet hat. DasSERVER_NAME
ist in der Serverkonfiguration definiert. Welche Sie verwenden, hängt davon ab, wofür Sie sie benötigen. Sie sollten jetzt jedoch erkennen, dass der eine ein vom Client gesteuerter Wert ist, der für die Verwendung in der Geschäftslogik möglicherweise nicht zuverlässig ist, und der andere ein vom Server gesteuerter Wert ist, der zuverlässiger ist. Sie müssen jedoch sicherstellen, dass der betreffende WebserverSERVER_NAME
korrekt konfiguriert ist. Am Beispiel von Apache HTTPD finden Sie hier einen Auszug aus der Dokumentation :Update : Nachdem Sie die Antwort von Pekka auf Ihre Frage überprüft haben, die einen Link zu Bobince's Antwort enthält , für die PHP immer
HTTP_HOST
den Wert zurückgeben würdeSERVER_NAME
, widerspricht dies meinen eigenen Erfahrungen mit PHP 4.x + Apache HTTPD 1.2.x vor einigen Jahren Ich habe etwas Staub aus meiner aktuellen XAMPP-Umgebung unter Windows XP (Apache HTTPD 2.2.1 mit PHP 5.2.8) geblasen, es gestartet, eine PHP-Seite erstellt, die beide Werte druckt, eine Java-TestanwendungURLConnection
zum Ändern desHost
Headers und erstellt Tests haben mich gelehrt, dass dies tatsächlich (fälschlicherweise) der Fall ist.Nachdem ich PHP zum ersten Mal vermutet und einige PHP-Fehlerberichte zu diesem Thema gelesen hatte, stellte ich fest, dass der Grund für das Problem im verwendeten Webserver liegt und dass der HTTP-
Host
Header beiSERVER_NAME
Anforderung fälschlicherweise zurückgegeben wurde. Also habe ich mich mit verschiedenen Schlüsselwörtern zum Thema in Apache HTTPD-Fehlerberichte vertieft und schließlich einen verwandten Fehler gefunden . Dieses Verhalten wurde seit Apache HTTPD 1.3 eingeführt. Sie müssen dieUseCanonicalName
Anweisungon
im<VirtualHost>
Eintrag desServerName
In festlegenhttpd.conf
(überprüfen Sie auch die Warnung am unteren Rand des Dokuments !).Das hat bei mir funktioniert.
Zusammenfassend
SERVER_NAME
ist es zuverlässiger, aber Sie sind abhängig von der Serverkonfiguration!quelle
server_name
Direktive festgelegten Wert zurückgibt . Besonders wenn nein gesetztserver_name
ist,_SERVER["SERVER_NAME"]
wird auch leer sein.HTTP_HOST
ist der vom Client gesendete Zielhost. Es kann vom Benutzer frei manipuliert werden. Es ist kein Problem, eine Anfrage an Ihre Site zu senden, in der Sie nach einemHTTP_HOST
Wert von gefragt werdenwww.stackoverflow.com
.SERVER_NAME
stammt aus derVirtualHost
Definition des Servers und wird daher als zuverlässiger angesehen. Es kann jedoch auch von außen unter bestimmten Bedingungen im Zusammenhang mit der Einrichtung Ihres Webservers manipuliert werden: Siehe diese SO-Frage , die sich mit den Sicherheitsaspekten beider Varianten befasst.Sie sollten sich auch nicht darauf verlassen, um sicher zu sein. Das heißt, was zu verwenden ist, hängt wirklich davon ab, was Sie tun möchten. Wenn Sie feststellen möchten, auf welcher Domain Ihr Skript ausgeführt wird, können Sie diese sicher verwenden
HTTP_HOST
, solange ungültige Werte, die von einem böswilligen Benutzer stammen, nichts beschädigen können.quelle
UseCanonicalName on
in httpd.conf verwenden, um zu erzwingenSERVER_NAME
, dass der tatsächliche Servername angegeben wird.$_SERVER['SERVER_NAME']
würde er nicht so gut funktionieren . Ein schlecht konfigurierter Server wird$_SERVER['SERVER_NAME']
basierend auf dem Wert der Clientanforderung festgelegtHost:
. Beide sind gleich.Wie in dieser Antwort erwähnt , enthält der Server den Port, wenn er auf einem anderen Port als 80 ausgeführt wird (wie dies auf einem Entwicklungs- / Intranetcomputer üblich ist)
HTTP_HOST
, währendSERVER_NAME
dies nicht der Fall ist.(Zumindest ist mir das bei Apache-Port-basierten virtuellen Hosts aufgefallen.)
Beachten Sie, dass
HTTP_HOST
dies nicht enthalten ist,:443
wenn Sie unter HTTPS ausgeführt werden (es sei denn, Sie verwenden einen nicht standardmäßigen Port, den ich nicht getestet habe).Wie andere angemerkt haben, unterscheiden sich die beiden auch bei der Verwendung von IPv6:
quelle
Bitte beachten Sie, dass Sie IPv6 wahrscheinlich verwenden möchten, wenn Sie IPv6 verwenden möchten
HTTP_HOST
eher als verwendenSERVER_NAME
. Wenn Siehttp://[::1]/
die Umgebungsvariablen eingeben , sind folgende:Dies bedeutet, dass Sie möglicherweise ein unangenehmes Ergebnis erhalten, wenn Sie beispielsweise einen mod_rewrite ausführen. Beispiel für eine SSL-Umleitung:
Dies gilt NUR, wenn Sie ohne Hostnamen auf den Server zugreifen.
quelle
https://%{SERVER_NAME}%{REQUEST_URI}
Wenn Sie eine server.php oder was auch immer überprüfen möchten, möchten Sie sie wie folgt aufrufen:
oder
Greifen Sie dann mit allen gültigen URLs für Ihre Website darauf zu und überprüfen Sie den Unterschied.
quelle
Kommt darauf an, was ich herausfinden will. SERVER_NAME ist der Hostname des Servers, während HTTP_HOST der virtuelle Host ist, mit dem der Client verbunden ist.
quelle
SERVER_NAME
ist normalerweise der Name des VirtualHost, nicht der Server selbst. Und in ApacheSERVER_NAME
wird häufig mit dem gleichen Wert wieHTTP_HOST
(siehe BalusCs Antwort) gefüllt.SERVER_NAME
für einen virtuellen Host gilt. Es kann jedoch weiterhin ein virtuelles Host-Setup für einen Standort verwendet werden. Viele Leute nutzen Shared Hosting, also verstehe ich Ihren Standpunkt.Ich habe eine Weile gebraucht, um zu verstehen, was Menschen unter "
SERVER_NAME
zuverlässiger" verstehen . Ich verwende einen gemeinsam genutzten Server und habe keinen Zugriff auf Anweisungen für virtuelle Hosts. Also benutze ich mod_rewrite in.htaccess
, um verschiedeneHTTP_HOST
s verschiedenen Verzeichnissen zuzuordnen . In diesem Fall ist esHTTP_HOST
sinnvoll.Ähnlich verhält es sich, wenn man namenbasierte virtuelle Hosts verwendet: Die
ServerName
Direktive innerhalb eines virtuellen Hosts gibt lediglich an, welcher Hostname diesem virtuellen Host zugeordnet wird. Unter dem Strich muss in beiden Fällen der vom Client während der Anfrage (HTTP_HOST
) angegebene Hostname mit einem Namen innerhalb des Servers abgeglichen werden, der selbst einem Verzeichnis zugeordnet ist. Ob die Zuordnung mit virtuellen Host-Direktiven oder mit htaccess mod_rewrite-Regeln erfolgt, ist hier zweitrangig. In diesen FällenHTTP_HOST
wird das gleiche sein wieSERVER_NAME
. Ich bin froh, dass Apache so konfiguriert ist.Bei IP-basierten virtuellen Hosts ist die Situation jedoch anders. In diesem Fall und nur in diesem Fall
SERVER_NAME
undHTTP_HOST
kann unterschiedlich sein, da der Client den Server jetzt anhand der IP-Adresse und nicht anhand des Namens auswählt. In der Tat kann es spezielle Konfigurationen geben, bei denen dies wichtig ist.Ab sofort werde ich also verwenden
SERVER_NAME
, nur für den Fall, dass mein Code in diesen speziellen Konfigurationen portiert wird.quelle
Angenommen, man hat ein einfaches Setup (CentOS 7, Apache 2.4.x und PHP 5.6.20) und nur eine Website (ohne virtuelles Hosting) ...
Im PHP-Sinne
$_SERVER['SERVER_NAME']
ist ein Element, das PHP im$_SERVER
Superglobal registriert, basierend auf Ihrer Apache-Konfiguration (**ServerName**
Direktive mitUseCanonicalName On
) in httpd.conf (sei es aus einer enthaltenen Konfigurationsdatei des virtuellen Hosts, was auch immer usw.). HTTP_HOST wird vom HTTP abgeleitethost
Header abgeleitet. Behandeln Sie dies als Benutzereingabe. Filtern und validieren Sie vor der Verwendung.Hier ist ein Beispiel, wo ich
$_SERVER['SERVER_NAME']
als Grundlage für einen Vergleich verwende. Die folgende Methode stammt aus einer konkreten untergeordneten Klasse, die ich mit dem NamenServerValidator
(child ofValidator
) erstellt habe.ServerValidator
Überprüft sechs oder sieben Elemente in $ _SERVER, bevor sie verwendet werden.Um festzustellen, ob die HTTP-Anforderung POST ist, verwende ich diese Methode.
Zum Zeitpunkt des Aufrufs dieser Methode wären alle Filter und Validierungen der relevanten $ _SERVER-Elemente erfolgt (und die relevanten Eigenschaften wurden festgelegt).
Die Linie ...
... prüft, ob der
$_SERVER['HTTP_HOST']
Wert (der letztendlich aus dem angefordertenhost
HTTP-Header abgeleitet wurde) übereinstimmt$_SERVER['SERVER_NAME']
.Nun, ich bin mit Superglobal sprechen , mein Beispiel zu erklären, aber das ist nur , weil einige Menschen sind nicht vertraut mit
INPUT_GET
,INPUT_POST
undINPUT_SERVER
in Bezug auffilter_input_array()
.Unter dem Strich verarbeite ich POST-Anfragen auf meinem Server nur, wenn alle vier Bedingungen erfüllt sind. In Bezug auf POST-Anforderungen bedeutet das Versagen der Bereitstellung eines HTTP-
host
Headers (auf frühere Tests getestet) für strenge HTTP 1.0- Browser das Schicksal . Darüber hinaus ist der angeforderte Host muss mit dem Wert übereinstimmen für in der httpd.conf , und durch Erweiterung, um den Wert für die in der Superglobal. Wieder würde ich mit den PHP-Filterfunktionen verwenden, aber Sie fangen meine Drift.ServerName
$_SERVER('SERVER_NAME')
$_SERVER
INPUT_SERVER
Beachten Sie, dass Apache häufig
ServerName
in Standardumleitungen verwendet wird (z. B. wenn der nachfolgende Schrägstrich von einer URL entfernt wird: Beispiel: http://www.foo.com wird zu http://www.foo.com/ ), auch wenn dies nicht der Fall ist Verwenden der URL-Umschreibung.Ich benutze
$_SERVER['SERVER_NAME']
als Standard nicht$_SERVER['HTTP_HOST']
. Zu diesem Thema gibt es viel Hin und Her.$_SERVER['HTTP_HOST']
könnte leer sein, daher sollte dies nicht die Grundlage für die Erstellung von Codekonventionen wie meiner oben beschriebenen öffentlichen Methode sein. Nur weil beide festgelegt werden können, ist dies jedoch keine Garantie dafür, dass sie gleich sind. Testen ist der beste Weg, um sicher zu wissen (unter Berücksichtigung der Apache-Version und der PHP-Version).quelle
Wie balusC sagte, ist SERVER_NAME nicht zuverlässig und kann in der Apache-Konfiguration, der Servernamen-Konfiguration des Servers und der Firewall geändert werden, die sich zwischen Ihnen und dem Server befinden können.
Die folgende Funktion gibt immer einen echten Host (vom Benutzer eingegebener Host) ohne Port zurück und ist fast zuverlässig:
quelle
$ _SERVER ['SERVER_NAME'] basiert auf der Konfiguration Ihres Webservers. $ _SERVER ['HTTP_HOST'] basiert auf der Anfrage des Clients.
quelle