Quelle est la différence entre PHP HTTP_HOST
et SERVER_NAME
PHP?
où:
HTTP_POST
===$_SERVER['HTTP_HOST']
SERVER_NAME
===$_SERVER['SERVER_NAME']
Quand envisageriez-vous d'utiliser l'un sur l'autre et pourquoi?
php
apache
server-variables
Emanuil Rusev
la source
la source
HTTP_HOST
. Sinon, un attaquant peut mettre n'importe quelle valeur dans la requête HTTPHost:
et obliger le serveur à l'accepter.$_SERVER['HTTP_HOST']
ou$_SERVER['SERVER_NAME']
Réponses:
Le
HTTP_HOST
est obtenu à partir de l' en-tête de requête HTTP et c'est ce que le client a réellement utilisé comme "hôte cible" de la requête. LeSERVER_NAME
est défini dans la configuration du serveur. Lequel utiliser dépend de ce dont vous avez besoin. Cependant, vous devez maintenant vous rendre compte que l'une est une valeur contrôlée par le client qui peut donc ne pas être fiable pour une utilisation dans la logique métier et l'autre est une valeur contrôlée par le serveur qui est plus fiable. Vous devez cependant vous assurer que le serveur Web en question estSERVER_NAME
correctement configuré. Prenant Apache HTTPD comme exemple, voici un extrait de sa documentation :Mise à jour : après avoir vérifié la réponse de Pekka à votre question qui contient un lien vers la réponse de Bobince pour laquelle PHP retournerait toujours
HTTP_HOST
la valeur deSERVER_NAME
, ce qui va à l'encontre de mes propres expériences PHP 4.x + Apache HTTPD 1.2.x d'il y a quelques années , J'ai soufflé de la poussière de mon environnement XAMPP actuel sur Windows XP (Apache HTTPD 2.2.1 avec PHP 5.2.8), l'ai démarré, créé une page PHP qui imprime les deux valeurs, créé une application de test Java en utilisantURLConnection
pour modifier l'en-Host
tête et les tests m'ont appris que c'est effectivement (incorrectement) le cas.Après avoir soupçonné PHP pour la première fois et avoir fouillé dans certains rapports de bogues PHP concernant le sujet, j'ai appris que la racine du problème se trouvait dans le serveur Web utilisé, qu'il renvoyait incorrectement l'en-
Host
tête HTTP lors de laSERVER_NAME
demande. J'ai donc fouillé dans les rapports de bogues Apache HTTPD en utilisant divers mots clés concernant le sujet et j'ai finalement trouvé un bogue connexe . Ce comportement a été introduit depuis environ Apache HTTPD 1.3. Vous devez définirUseCanonicalName
directiveon
dans l'<VirtualHost>
entrée duServerName
danshttpd.conf
(vérifiez aussi la mise en garde au bas du document !).Cela a fonctionné pour moi.
En résumé,
SERVER_NAME
est plus fiable, mais vous êtes dépendant de la configuration du serveur!la source
server_name
directive. Surtout si aucunserver_name
n'est défini, il_SERVER["SERVER_NAME"]
sera également vide.HTTP_HOST
est l'hôte cible envoyé par le client. Il peut être manipulé librement par l'utilisateur. Ce n'est pas un problème pour envoyer une demande à votre site demandant uneHTTP_HOST
valeur dewww.stackoverflow.com
.SERVER_NAME
provient de laVirtualHost
définition du serveur et est donc considéré comme plus fiable. Cependant, il peut également être manipulé de l'extérieur sous certaines conditions liées à la configuration de votre serveur Web: voir cette question SO qui traite des aspects de sécurité des deux variantes.Vous ne devriez pas compter sur l'un ou l'autre pour être en sécurité. Cela dit, ce que vous utilisez dépend vraiment de ce que vous voulez faire. Si vous souhaitez déterminer sur quel domaine votre script s'exécute, vous pouvez l'utiliser en toute sécurité
HTTP_HOST
tant que les valeurs non valides provenant d'un utilisateur malveillant ne peuvent rien casser.la source
UseCanonicalName on
dans httpd.conf pour forcerSERVER_NAME
à être le nom réel du serveur.$_SERVER['SERVER_NAME']
cela ne fonctionnerait pas aussi bien . Un serveur mal configuré sera défini en$_SERVER['SERVER_NAME']
fonction de la valeur de laHost:
demande du client . Les deux sont égaux.Comme je l'ai mentionné dans cette réponse , si le serveur s'exécute sur un port autre que 80 (comme cela peut être courant sur une machine de développement / intranet), il
HTTP_HOST
contient alors le port, alors que ceSERVER_NAME
n'est pas le cas.(C'est du moins ce que j'ai remarqué dans les hôtes virtuels basés sur le port Apache)
Notez que
HTTP_HOST
cela ne contient pas:443
lors de l'exécution sur HTTPS (sauf si vous exécutez sur un port non standard, que je n'ai pas testé).Comme d'autres l'ont noté, les deux diffèrent également lors de l'utilisation d'IPv6:
la source
Veuillez noter que si vous souhaitez utiliser IPv6, vous préférez probablement utiliser
HTTP_HOST
plutôt queSERVER_NAME
. Si vous entrezhttp://[::1]/
les variables d'environnement seront les suivantes:Cela signifie que si vous faites un mod_rewrite par exemple, vous pourriez obtenir un résultat désagréable. Exemple pour une redirection SSL:
Cela s'applique UNIQUEMENT si vous accédez au serveur sans nom d'hôte.
la source
https://%{SERVER_NAME}%{REQUEST_URI}
Si vous souhaitez vérifier via un server.php ou autre chose, vous voulez l'appeler comme suit:
ou
Accédez-y ensuite avec toutes les URL valides de votre site et découvrez la différence.
la source
Cela dépend de ce que je veux découvrir. SERVER_NAME est le nom d'hôte du serveur, tandis que HTTP_HOST est l'hôte virtuel auquel le client s'est connecté.
la source
SERVER_NAME
est généralement le nom du VirtualHost, pas le serveur lui-même. Et dans Apache,SERVER_NAME
est souventHTTP_HOST
rempli avec la même valeur que (voir la réponse de BalusC).SERVER_NAME
s'applique à un hôte virtuel. Cependant, on peut toujours utiliser une configuration d'hôte virtuel pour un site. Beaucoup de gens utilisent l'hébergement partagé, donc je vois votre point.Il m'a fallu un certain temps pour comprendre ce que les gens entendaient par «
SERVER_NAME
est plus fiable». J'utilise un serveur partagé et je n'ai pas accès aux directives d'hôte virtuel. Donc, j'utilise mod_rewrite dans.htaccess
pour mapper différentsHTTP_HOST
s à différents répertoires. Dans ce cas, c'estHTTP_HOST
significatif.La situation est similaire si l'on utilise des hôtes virtuels basés sur le nom: la
ServerName
directive dans un hôte virtuel indique simplement quel nom d'hôte sera mappé à cet hôte virtuel. L'essentiel est que, dans les deux cas, le nom d'hôte fourni par le client lors de la demande (HTTP_HOST
), doit être mis en correspondance avec un nom au sein du serveur, lui-même mappé à un répertoire. Que le mappage soit effectué avec des directives d'hôte virtuel ou avec des règles htaccess mod_rewrite est secondaire ici. Dans ces cas,HTTP_HOST
sera le même queSERVER_NAME
. Je suis heureux qu'Apache soit configuré de cette façon.Cependant, la situation est différente avec les hôtes virtuels basés sur IP. Dans ce cas et seulement dans ce cas,
SERVER_NAME
etHTTP_HOST
peut être différent, car maintenant le client sélectionne le serveur par l'IP, pas par le nom. En effet, il peut y avoir des configurations spéciales lorsque cela est important.Donc, à partir de maintenant, je vais utiliser
SERVER_NAME
, juste au cas où mon code serait porté dans ces configurations spéciales.la source
En supposant qu'un a une configuration simple (CentOS 7, Apache 2.4.x et PHP 5.6.20) et un seul site Web (ne supposant pas d'hébergement virtuel) ...
Au sens PHP,
$_SERVER['SERVER_NAME']
est un élément que PHP enregistre dans le$_SERVER
superglobal en fonction de votre configuration Apache (**ServerName**
directive avecUseCanonicalName On
) dans httpd.conf (que ce soit à partir d'un fichier de configuration d'hôte virtuel inclus, peu importe, etc ...). HTTP_HOST est dérivé de l'en-host
tête HTTP . Traitez cela comme une entrée utilisateur. Filtrez et validez avant d'utiliser.Voici un exemple où j'utilise
$_SERVER['SERVER_NAME']
comme base pour une comparaison. La méthode suivante est issue d'une classe enfant concrète que j'ai créée nomméeServerValidator
(enfant deValidator
).ServerValidator
vérifie six ou sept éléments dans $ _SERVER avant de les utiliser.Pour déterminer si la requête HTTP est POST, j'utilise cette méthode.
Au moment où cette méthode est appelée, tous les filtrages et validations des éléments $ _SERVER pertinents se seraient produits (et les propriétés pertinentes définies).
La ligne ...
... vérifie que la
$_SERVER['HTTP_HOST']
valeur (finalement dérivée de l'host
en-tête HTTP demandé ) correspond$_SERVER['SERVER_NAME']
.Maintenant, je me sers de parler superglobale pour expliquer mon exemple, mais c'est juste parce que certaines personnes ne connaissent pas
INPUT_GET
,INPUT_POST
etINPUT_SERVER
en ce qui concernefilter_input_array()
.L'essentiel est que je ne traite pas les demandes POST sur mon serveur à moins que les quatre conditions ne soient remplies. Par conséquent, en termes de requêtes POST, le fait de ne pas fournir un en-
host
tête HTTP (présence testée pour plus tôt) est fatal pour les navigateurs HTTP 1.0 stricts . De plus, l'hôte demandé doit correspondre à la valeur deServerName
dans le httpd.conf et, par extension, à la valeur de$_SERVER('SERVER_NAME')
dans le$_SERVER
superglobal. Encore une fois, j'utiliseraisINPUT_SERVER
avec les fonctions de filtre PHP, mais vous attrapez ma dérive.Gardez à l' esprit que Apache utilise fréquemment
ServerName
dans standards réoriente ( par exemple en laissant le slash hors URL: Exemple, http://www.foo.com devenir http://www.foo.com/ ), même si vous n'êtes pas en utilisant la réécriture d'URL.J'utilise
$_SERVER['SERVER_NAME']
comme standard, non$_SERVER['HTTP_HOST']
. Il y a beaucoup de va-et-vient sur cette question.$_SERVER['HTTP_HOST']
pourrait être vide, donc cela ne devrait pas être la base pour créer des conventions de code telles que ma méthode publique ci-dessus. Mais, tout simplement parce que les deux peuvent être définis ne garantit pas qu'ils seront égaux. Le test est le meilleur moyen de savoir avec certitude (en gardant à l'esprit la version Apache et la version PHP).la source
Comme balusC l'a dit, SERVER_NAME n'est pas fiable et peut être modifié dans la configuration d'apache, la configuration du nom de serveur du serveur et le pare-feu qui peut se trouver entre vous et le serveur.
La fonction suivante retourne toujours un véritable hôte (hôte tapé par l'utilisateur) sans port et c'est presque fiable:
la source
$ _SERVER ['SERVER_NAME'] est basé sur la configuration de vos serveurs Web. $ _SERVER ['HTTP_HOST'] est basé sur la demande du client.
la source