Frage

Als würde Sie überlegen, eine über der anderen und warum?

War es hilfreich?

Lösung

Die HTTP_HOST wird aus dem erhaltenen HTTP-Request-Header und das ist, was eigentlich der Kunde als „Ziel-Host“ der Anforderung verwendet. Die SERVER_NAME wird in Server-Konfiguration definiert. Die man zu verwenden, hängt ab, was Sie brauchen es für. Sie sollen nun jedoch erkennen, dass derjenige ein Client gesteuerten Wert ist, der somit nicht für den Einsatz in Business-Logik zuverlässig sein kann und der andere ist ein servergesteuerten Wert, die zuverlässiger ist. Sie müssen jedoch sicherstellen, dass der Webserver in Frage hat sich die SERVER_NAME richtig konfiguriert ist. Unter Apache als Beispiel, hier ist ein Auszug aus seiner Dokumentation :

  

Wenn kein ServerName angegeben wird, dann versucht der Server die Hostnamen abzuleiten durch einen Reverse-Lookup auf der IP-Adresse ausgeführt wird. Wenn kein Port in den ServerName angegeben wird, dann wird der Server den Port aus der eingehenden Anfrage verwenden. Für eine optimale Zuverlässigkeit und Berechenbarkeit, sollten Sie einen expliziten Hostnamen und Port mit der ServerName Direktive angeben.


Aktualisieren : Nach Prüfung der Antwort von Pekka auf Ihre Frage , die einen Link zu Antwort der bobince dass PHP immer HTTP_HOST Wert für SERVER_NAME zurückkehren würde, die gegen meine eigene PHP geht 4.x + Apache 1.2.x Erfahrungen aus einem vor Jahren Paar, ich etwas Staub von meiner aktuellen XAMPP-Umgebung unter Windows XP blies (Apache 2.2.1 mit PHP 5.2.8), begann es, eine PHP-Seite erstellt, die die beiden Werte drucken, erstellt mit Hilfe eine Java-Testanwendung < a href = "http://docs.oracle.com/javase/8/docs/api/java/net/URLConnection.html" rel = "noreferrer"> URLConnection die Host Header und Tests zu modifizieren, hat mich gelehrt, dass dies in der Tat ist (falsch) der Fall ist.

Nach dem ersten Verdächtigungen PHP und Graben in einigen PHP Bug Berichte das Thema in Bezug auf, erfuhr ich, dass die Wurzel des Problems in Web-Server verwendet wird, dass es falsch HTTP zurück Host Header, wenn SERVER_NAME angefordert wurde. Also grub ich in Apache HTTPD Bug-Reports verschiedene Schlüsselwörter in Bezug auf das Thema und ich fand schließlich einen ähnlichen Fehler . Dieses Verhalten wurde seit etwa Apache 1.3 eingeführt. Sie müssen Set UseCanonicalName Richtlinie on im <VirtualHost> Eintrag von die ServerName in httpd.conf (auch die Warnung überprüfen am unteren Rand des das Dokument !).

<VirtualHost *>
    ServerName example.com
    UseCanonicalName on
</VirtualHost> 

Das ist für mich gearbeitet.

Verdichtete, SERVER_NAME ist zuverlässiger, aber du bist abhängig auf dem Server Config!

Andere Tipps

HTTP_HOST ist die Ziel-Host durch den Client gesendet. Es kann vom Anwender frei manipuliert werden. Es ist kein Problem, eine Anfrage zu Ihrer Website für einen HTTP_HOST Wert von www.stackoverflow.com bitten zu senden.

kommt SERVER_NAME aus dem VirtualHost Definition des Servers und ist daher zuverlässiger betrachtet. Es kann jedoch auch von außen unter bestimmten Bedingungen, wie Sie Ihren Web-Server eingerichtet ist, im Zusammenhang manipuliert werden: Sehen Sie diese Diese Frage SO die sie mit den Sicherheitsaspekten beiden Varianten.

Sie sollten auch nicht verlassen sich auf, sicher zu sein. Das heißt, was wirklich zu verwenden, hängt davon ab, was Sie tun wollen. Wenn Sie ermitteln möchten, welche Domain-Skript ausgeführt wird, können Sie sicher HTTP_HOST verwenden, solange ungültige Werte von einem böswilligen Benutzer kommt nichts kaputt machen kann.

Wie ich erwähnt in diese Antwort , wenn der Server läuft auf einem anderen Port als 80 (wie üblich sein könnte auf eine Entwicklung / Intranet-Maschine), dann enthält HTTP_HOST den Hafen, während SERVER_NAME nicht.

$_SERVER['HTTP_HOST'] == 'localhost:8080'
$_SERVER['SERVER_NAME'] == 'localhost'

(zumindest das ist, was ich in Apache Port-basierten Virtual bemerkt habe)

Beachten Sie, dass HTTP_HOST tut nicht :443 enthalten, wenn auf HTTPS läuft (es sei denn, Sie auf einem Nicht-Standard-Port laufen lassen, die ich nicht getestet).

Wie andere erwähnt haben, die beiden unterscheiden sich auch bei Verwendung von IPv6:

$_SERVER['HTTP_HOST'] == '[::1]'
$_SERVER['SERVER_NAME'] == '::1'

Bitte beachten Sie, dass, wenn Sie IPv6 verwenden möchten, möchten Sie wahrscheinlich zu verwenden HTTP_HOST statt SERVER_NAME. Wenn Sie die Umgebungsvariablen eingeben http://[::1]/ wird wie folgt vor:

HTTP_HOST = [::1]
SERVER_NAME = ::1

Das bedeutet, dass, wenn Sie eine mod_rewrite zum Beispiel tun, könnte man ein böses Ergebnis. Beispiel für eine SSL-Umleitung:

# SERVER_NAME will NOT work - Redirection to https://::1/
RewriteRule .* https://%{SERVER_NAME}/

# HTTP_HOST will work - Redirection to https://[::1]/
RewriteRule .* https://%{HTTP_HOST}/

Dies gilt nur, wenn Sie den Server ohne einen Hostnamen zugreifen zu können.

Wenn Sie durch eine server.php überprüfen oder was auch immer Sie es mit dem folgenden nennen:

<?php

phpinfo(INFO_VARIABLES);

?>

oder

<?php

header("Content-type: text/plain");

print_r($_SERVER);

?>

Zugriff Dann ist es mit allen gültigen URLs für Ihre Website und überprüfen Sie den Unterschied aus.

Hängt, was ich herausfinden möchte. SERVER_NAME ist der Hostname des Servers, während HTTP_HOST die virtuelle Host ist, dass der Client verbunden ist.

Es dauerte eine Weile, um zu verstehen, was gemeint Menschen SERVER_NAME zuverlässiger ist. " Ich benutze einen gemeinsam genutzten Server und haben keinen Zugriff auf virtuelle Host-Richtlinien. Also, ich benutze mod_rewrite in .htaccess verschiedene HTTP_HOSTs auf verschiedene Verzeichnisse zu kartieren. In diesem Fall ist es HTTP_HOST, die sinnvoll ist.

Die Situation ist ähnlich, wenn man Anwendungen namensbasierte virtuelle Hosts: die ServerName Richtlinie innerhalb eines virtuellen Host sagt einfach die Hostnamen wird zu diesem virtuellen Host zugeordnet werden. Das Endergebnis ist, dass in beiden Fällen der Hostname des Kunden während der Anforderung (HTTP_HOST) vorgesehen sind, müssen mit einem Namen innerhalb des Servers angepasst werden, die selbst in einem Verzeichnis zugeordnet. Ob die Abbildung mit virtuellen Host-Richtlinien durchgeführt oder mit .htaccess mod_rewrite Regeln ist hier zweitrangig. In diesen Fällen HTTP_HOST die gleiche wie SERVER_NAME sein. Ich bin froh, dass Apache auf diese Weise konfiguriert ist.

Allerdings ist die Situation anders mit IP-basierten virtuellen Hosts. In diesem Fall und nur in diesem Fall SERVER_NAME und HTTP_HOST kann unterschiedlich sein, weil jetzt der Client wählt den Server durch die IP, nicht mit Namen. Ja, es könnte sein, spezielle Konfigurationen, bei denen dies wichtig ist.

Also, ab jetzt werde ich SERVER_NAME verwenden, falls mein Code in diesen speziellen Konfigurationen portiert wird.

Vorausgesetzt, man hat eine einfache setup (CentOS 7, Apache 2.4.x und PHP 5.6.20) und nur eine website (nicht vorausgesetzt, virtual hosting) ...

In der PHP-Sinn, $_SERVER['SERVER_NAME'] ist ein element, PHP-Register in der $_SERVER superglobale basierend auf Ihrer Apache-Konfiguration (**ServerName** Richtlinie UseCanonicalName On ) in httpd.conf (sei es aus einer mitgelieferten virtual-host-Konfiguration-Datei, was auch immer, etc ...). HTTP_HOST ist abgeleitet aus der HTTP - host header.Behandeln Sie dies als Benutzer Eingang.Filter und überprüfen, bevor Sie verwenden.

Hier ist ein Beispiel, wo ich es verwenden $_SERVER['SERVER_NAME'] als Grundlage für einen Vergleich.Die folgende Methode ist von einem konkreten Kind-Klasse benannt, die ich gemacht ServerValidator (Kind Validator). ServerValidator Prüfungen mit sechs oder sieben Elemente in $_SERVER bevor Sie Sie verwenden.

Bei der Bestimmung, ob die HTTP-Anforderung ist die POST, ich benutze diese Methode.

public function isPOST()
{
    return (($this->requestMethod === 'POST')    &&  // Ignore
            $this->hasTokenTimeLeft()            &&  // Ignore
            $this->hasSameGETandPOSTIdentities() &&  // Ingore
            ($this->httpHost === filter_input(INPUT_SERVER, 'SERVER_NAME')));
}

Wenn diese Methode aufgerufen wird, alle die Filterung und Validierung der einschlägigen $_SERVER Elemente eingetreten wäre (und die entsprechenden Eigenschaften festlegen).

Die Linie ...

($this->httpHost === filter_input(INPUT_SERVER, 'SERVER_NAME')

...überprüft, dass die $_SERVER['HTTP_HOST'] Wert (letztlich abgeleitet aus der die angeforderten host HTTP-header) entspricht $_SERVER['SERVER_NAME'].

Nun, ich bin mit superglobale sprechen, um zu erklären, mein Beispiel, aber das ist nur weil einige Leute nicht kennen INPUT_GET, INPUT_POST, und INPUT_SERVER in Bezug auf die filter_input_array().

Das Fazit ist, dass ich nicht damit umgehen, POST-Anfragen an meinen server, es sei denn, alle vier Bedingungen erfüllt sind.Daher, in Bezug auf POST-Anfragen, Fehler zu bieten eine HTTP - host header (Vorhandensein geprüft früher) Zaubersprüche doom für strenge HTTP 1.0 Browser.Darüber hinaus werden die angeforderten host muss dem Wert entsprechen, der für ServerName in der httpd.conf, und, durch Erweiterung, die Wert für die $_SERVER('SERVER_NAME') in der $_SERVER superglobale.Wieder, ich wäre mit INPUT_SERVER mit der PHP-filter-Funktionen, aber Sie fangen meine drift.

Beachten Sie, dass der Apache verwendet Häufig ServerName in standard-Umleitungen (wie verlassen Sie den abschließenden Schrägstrich aus einer URL:Beispiel http://www.foo.com immer http://www.foo.com/), auch wenn Sie nicht mit URL-rewriting.

Ich benutze $_SERVER['SERVER_NAME'] als standard ist nicht $_SERVER['HTTP_HOST'].Es gibt eine Menge hin und her zu diesem Thema. $_SERVER['HTTP_HOST'] leer sein könnten, so sollte dies nicht werden die Grundlage für die Erstellung von code-Konventionen wie mein public-Methode vor.Aber, nur weil beide gesetzt werden können nicht garantieren, werden Sie gleich.Testen ist der beste Weg, sicher zu wissen (bearing in mind Apache-version und die PHP-version).

Wie balusC sagte SERVER_NAME nicht zuverlässig ist und in Apache-Konfiguration, Servernamen Config des Servers geändert werden und Firewall, die zwischen Ihnen und dem Server sein können.

Nach Funktion zurückkehren immer real Host (Benutzer eingegeben Host) ohne Port und es ist fast sicher:

function getRealHost(){
   list($realHost,)=explode(':',$_SERVER['HTTP_HOST']);
   return $realHost;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top