PHP'de HTTP_HOST ve SERVER_NAME arasındaki fark nedir?


533

Arasındaki fark nedir HTTP_HOSTve SERVER_NAMEPHP?

nerede:

  • HTTP_POST === $_SERVER['HTTP_HOST']
  • SERVER_NAME === $_SERVER['SERVER_NAME']

Ne zaman diğerinin üzerinde kullanmayı düşünürdünüz ve neden?


14
"Normalde HTTP_HOST'a giderim, böylece kullanıcı açtıkları ana bilgisayar adı üzerinde kalır. Örneğin, bir .com ve .org alan adında aynı siteye sahipsem .org'dan birisine bir şey göndermek istemiyorum .com, özellikle .org üzerinde diğer alan adına gönderildiklerinde kaybedecekleri giriş belirteçleri varsa. " - Bu ve diğer ilginç noktalar stackoverflow.com/questions/1459739/…
Yarin

5
@Yarin, sonuçlarını beyaz listeyeHTTP_HOST eklemeyi unutmayın . Aksi takdirde, bir saldırgan HTTP'nin isteğine herhangi bir değer ekleyebilir Host:ve sunucunun kabul etmesini sağlayabilir.
Pacerier

6
Yeni Başlayanlar: Bu soru, tipik olarak $_SERVER['HTTP_HOST']veya$_SERVER['SERVER_NAME']
Gregory Cosmo Haun ile

Yanıtlar:


780

HTTP_HOSTElde edilir HTTP isteği başlık ve bu istemci aslında isteği "hedef konakçı" olarak kullanılmaktadır şeydir. SERVER_NAMESunucu geneli tanımlanmıştır. Hangisini kullanmanız, neye ihtiyacınız olduğuna bağlıdır. Ancak şimdi, birinin iş mantığında kullanım için güvenilir olmayabilecek bir müşteri kontrollü değer olduğunu ve diğerinin daha güvenilir olan sunucu kontrollü bir değer olduğunu anlamalısınız. Ancak, söz konusu web sunucusunun SERVER_NAMEdoğru yapılandırıldığından emin olmanız gerekir . Apache HTTPD'yi örnek alarak, işte onun dokümanlarından bir alıntı :

Hayır ServerNamebelirtilirse, sunucu IP adresi üzerinde geriye doğru arama yaparak ana makine adını bulmaya çalışır. Bölümünde herhangi bir bağlantı noktası belirtilmezse ServerName, sunucu gelen istekten bağlantı noktasını kullanır. Optimum güvenilirlik ve öngörülebilirlik için, ServerNameyönergeyi kullanarak açık bir ana bilgisayar adı ve bağlantı noktası belirtmelisiniz .


Güncelleme : Pekka'nın cevabını kontrol ettikten sonra , PHP'nin her zaman için değerinin geri döneceği bobince'nin cevabına bir bağlantı içeren , birkaç yıl önce kendi PHP 4.x + Apache HTTPD 1.2.x deneyimlerime karşı çıkıyor , Windows XP'de (PHP 5.2.8 ile Apache HTTPD 2.2.1) mevcut XAMPP ortamımdan bir miktar toz patlattım, başlattım, her iki değeri de basan bir PHP sayfası oluşturdum , üstbilgiyi değiştirmek için bir Java test uygulaması oluşturduk ve testler bana bunun (yanlış) durum olduğunu öğretti.HTTP_HOSTSERVER_NAMEURLConnectionHost

İlk önce PHP'den şüphelenip konu ile ilgili bazı PHP hata raporlarını kazdıktan sonra , sorunun kökünün kullanılan web sunucusunda olduğunu , istendiğinde yanlış HTTP Hostbaşlığını döndürdüğünü öğrendim SERVER_NAME. Bu yüzden konu ile ilgili çeşitli anahtar kelimeler kullanarak Apache HTTPD hata raporlarına girdim ve sonunda ilgili bir hata buldum . Bu davranış, Apache HTTPD 1.3 çevresinde tanıtıldı. Sen seti gerekir için direktif içinde girişi in (aynı zamanda alt kısmında uyarı kontrol belgesinde !).UseCanonicalNameon<VirtualHost>ServerNamehttpd.conf

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

Bu benim için çalıştı.

Özetlendi, SERVER_NAMEdaha güvenilir, ancak sunucu yapılandırmasına bağımlısınız !


5
Tamam, bu OP ile ilgisi olmayan ancak alakalı olan sorunumu çözdü. Bir tarayıcının sağlayabileceği herhangi bir şeyi kullanarak güvenlik sorunları konusunda çok endişeliydim. Bu cevap çok büyük bir yardımdı. Bir araya getirmek için zaman ayırdığınız için teşekkür ederiz.
Yitzhak

2
Neden HTTP_HOST'un güvenilir olmadığını söylüyorsunuz? Evet, kullanıcı tarafından sağlanır, ancak kullanıcı sahte bir değer verirse, sunucu yapılandırmanız otomatik olarak 503 döndürür ve PHP komut dosyanız çalıştırılmaz!
Pacerier

1
@Pacerier: Bu cevabı yazarken, olmadı. Yanıtlarda sürümler belirtilmiştir. Artık PHP ile devam etmeyin, bu yüzden gerçekten daha yeni bir sürümde değişti diyemeyiz.
BalusC

2
WinXP'den Apache'yi kandırmanın kolay bir yolu, 'hosts' dosyasına sunucunun IP'sinin aşağıdaki gibi başka bir alana atandığını belirten bir satır eklemektir: "127.0.0.1 etkialanim.com". Bunu, internet bağlantımın ve sitenin gerçekten hızlı yüklendiğimi düşünmek için kitlemizi kandırarak yerel bir web sitesini göstermek için birçok kez kullandım. Diğer yöne gidebilir ve "173.194.41.5 localhost" ile yerel olarak çalıştığını düşünmek için Apache'yi kandırabilirsiniz, bu yüzden Apache'nizin iyi yapılandırıldığından emin olmadıkça SERVER_NAME ürününe tam olarak güvenmemelisiniz.
vicenteherrera

1
Sadece eklemek istiyorum, bu NGINX + PHP-FPM server_namedirektif tarafından belirlenen değeri döndürür . Özellikle hayır server_nameayarlanmışsa da _SERVER["SERVER_NAME"]boş olacaktır.
white_gecko

69

HTTP_HOSTistemci tarafından gönderilen hedef ana bilgisayardır. Kullanıcı tarafından serbestçe manipüle edilebilir. Sitenize HTTP_HOSTdeğeri isteyen bir istek göndermek sorun değil www.stackoverflow.com.

SERVER_NAMEsunucunun VirtualHosttanımından gelir ve bu nedenle daha güvenilir kabul edilir. Bununla birlikte, web sunucunuzun nasıl kurulduğuna ilişkin belirli koşullar altında dışarıdan da değiştirilebilir: Bkz . Her iki varyasyonun güvenlik yönleriyle ilgili bu SO sorusu .

Güvenli olmak için ikisine de güvenmemelisiniz. Bununla birlikte, ne kullanacağınız gerçekten ne yapmak istediğinize bağlıdır. Komut dosyanızın hangi etki alanında çalıştığını belirlemek istiyorsanız, HTTP_HOSTkötü niyetli bir kullanıcıdan gelen geçersiz değerler hiçbir şeyi kıramadığı sürece güvenle kullanabilirsiniz .


8
Evet, ancak www.stackoverflow.com HTTP_HOST değeri isteyen bir istek, çoğu HTTP sunucusu tarafından reddedilir, böylece PHP betiği isteği bile görmez!
Pacerier

2
@Pacerier true, ancak sunucu düzgün yapılandırılmadıysa her zaman değil.
Pekka

1
BalusC'un gönderisinde belirtildiği gibi, bir Apache sanal ana bilgisayarına IP ile eriştiğinizde , bu değişkenlerin her ikisi de gerçek sunucu adını değil, IP'yi (varsayılan olarak) içerir. Gerçek sunucu adı olmaya UseCanonicalName onzorlamak SERVER_NAMEiçin httpd.conf içinde kullanmanız gerekir.
Simon East

@Pekka 웃, Sunucu düzgün yapılandırılmamışsa $_SERVER['SERVER_NAME']da çalışmaz . Kötü yapılandırılmış bir sunucu $_SERVER['SERVER_NAME'], istemcinin Host:isteğinin değerine göre ayarlanır . Her ikisi de eşit.
Pacerier

İyi cevap, ama sanal barındırma kabul etmem.
Anthony Rutledge

55

Bu cevapta bahsettiğim gibi , sunucu 80 dışında bir bağlantı noktasında çalışıyorsa (bir geliştirme / intranet makinesinde ortak olabileceği gibi) HTTP_HOSTbağlantı noktasını içerir, ancak SERVER_NAMEiçermez.

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

(En azından Apache port tabanlı sanal ana bilgisayarlarda bunu fark ettim)

Not HTTP_HOSTyok değil içeriyor :443HTTPS çalışırken (eğer ben test etmedim standart olmayan bir port, çalışan sürece).

Diğerlerinin de belirttiği gibi, ikisi de IPv6 kullanırken farklılık gösterir:

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

2
Bu sinsi davranışı ne zaman çözecekler?
Pacerier

27

Eğer IPv6 kullanmak istiyorsanız, muhtemelen kullanmak istediğiniz unutmayınız HTTP_HOSTziyade SERVER_NAME. http://[::1]/Ortam değişkenlerini girerseniz aşağıdaki değişkenler olacaktır:

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

Bu, örneğin bir mod_rewrite yaparsanız, kötü bir sonuç elde edebileceğiniz anlamına gelir. SSL yönlendirmesi örneği:

# 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}/

Bu SADECE sunucuya ana bilgisayar adı olmadan erişiyorsanız geçerlidir.


1
SiteGround, http:// https yönlendirme kodunda kendi https://%{SERVER_NAME}%{REQUEST_URI}
kurumlarında

6

Bir server.php dosyasını ya da herhangi bir şeyi kontrol etmek isterseniz, aşağıdakilerle aramak istersiniz:

<?php
    phpinfo(INFO_VARIABLES);
?>

veya

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

    print_r($_SERVER);
?>

Ardından siteniz için geçerli tüm URL'lerle erişin ve aradaki farkı inceleyin.


5

Ne bulmak istediğime bağlı. SERVER_NAME, sunucunun ana bilgisayar adı iken HTTP_HOST, istemcinin bağlandığı sanal ana bilgisayardır.


4
Tam olarak doğru değil Rowland, SERVER_NAMEgenellikle sunucunun kendisi değil, VirtualHost'un adıdır. Ve Apache'de SERVER_NAMEgenellikle aynı değerle doldurulur HTTP_HOST(bkz. BalusC'nin cevabı).
Simon East

1
@Simon, Çoğu ana bilgisayar şimdi VirtualHost olduğundan, "sunucunun kendisi" adıyla ne demek istersiniz?
Pacerier

Bir web sitesiyle sanal özel sunucu (VPS) çalıştırıyorsanız SERVER_NAME, bunun sanal bir ana bilgisayar için geçerli olduğunu varsaymanıza gerek yoktur . Ancak, bir site için sanal ana bilgisayar kurulumu kullanılabilir. Birçok kişi paylaşılan barındırma kullanıyor, bu yüzden amacınızı görüyorum.
Anthony Rutledge

2

İnsanların ' SERVER_NAMEdaha güvenilir' olduğunu kastettiklerini anlamak biraz zaman aldı . Paylaşılan bir sunucu kullanıyorum ve sanal ana bilgisayar yönergelerine erişimi yok. Yani, mod_rewrite farklı dizinleri .htaccess farklı HTTP_HOSTs eşlemek için kullanın . Bu durumda, bu HTTP_HOSTanlamlı.

Birisi ad tabanlı sanal ana bilgisayarlar kullanıyorsa durum benzerdir: sanal ana bilgisayardaki ServerNameyönerge, hangi ana bilgisayar adının bu sanal ana bilgisayara eşleneceğini söyler. Sonuçta, her iki durumda da, istek ( HTTP_HOST) sırasında istemci tarafından sağlanan ana bilgisayar adının, sunucu içindeki bir diziyle eşlenen bir adla eşleştirilmesi gerektiğidir. Eşlemenin sanal ana bilgisayar yönergeleri veya htaccess mod_rewrite kuralları ile yapılıp yapılmadığı burada ikincildir. Bu durumlarda, HTTP_HOSTaynı olacaktır SERVER_NAME. Apache'nin bu şekilde yapılandırıldığından memnunum.

Ancak IP tabanlı sanal ana bilgisayarlarda durum farklıdır. Bu durumda ve sadece bu durumda, SERVER_NAMEve HTTP_HOSTşimdi müşteri ile tanımasını IP tarafından sunucuyu seçer, çünkü farklı olabilir. Gerçekten de, bunun önemli olduğu özel konfigürasyonlar olabilir.

Bu nedenle, SERVER_NAMEkodumun bu özel yapılandırmalarda taşınması durumunda, bundan sonra kullanacağım .


2

Birinin basit bir kurulumu (CentOS 7, Apache 2.4.x ve PHP 5.6.20) ve sadece bir web sitesi (sanal barındırma olduğunu varsaymıyor) olduğunu varsayarsak ...

PHP anlamda, $_SERVER['SERVER_NAME']PHP'nin $_SERVERsüper küreselde httpd.conf'daki Apache yapılandırmanıza ( **ServerName**direktif ile UseCanonicalName On) dayalı olarak kaydedilen bir öğedir (dahil edilen sanal ana bilgisayar yapılandırma dosyasından, vb. Olsun). HTTP_HOST , HTTP hostüstbilgisinden türetilir . Bunu kullanıcı girişi olarak kabul edin. Kullanmadan önce filtreleyin ve doğrulayın.

İşte $_SERVER['SERVER_NAME']bir karşılaştırma için temel olarak kullandığım bir örnek . Aşağıdaki yöntem, adlandırılmış ServerValidator(çocuğu Validator) adında somut bir çocuk sınıfından alınmıştır . ServerValidatorkullanmadan önce $ _SERVER içindeki altı veya yedi öğeyi kontrol eder.

HTTP isteğinin POST olup olmadığını belirlerken bu yöntemi kullanıyorum.

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

Bu yöntemin çağrılmasıyla, ilgili $ _SERVER öğelerinin tüm filtreleme ve doğrulama işlemleri gerçekleşir (ve ilgili özellikler ayarlanır).

Çizgi ...

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

... $_SERVER['HTTP_HOST'](sonuçta istenen hostHTTP üstbilgisinden türetilmiş) değerin eşleşip eşleşmediğini denetler $_SERVER['SERVER_NAME'].

Şimdi, benim örnek açıklamak için süper küresel konuşmasına kullanıyorum, ama bu bazı insanlar aşina sırf olduğunu INPUT_GET, INPUT_POSTve INPUT_SERVERaçısından etmek filter_input_array().

Sonuçta sürece benim sunucuda POST isteklerini ilgilenmem, olan bütün dört şartlar yerine getirildiği. Bu nedenle, POST istekleri açısından, bir HTTP hostüstbilgisi sağlanamaması (daha önce test edilmiş olma durumu) katı HTTP 1.0 tarayıcıları için kıyameti yazmaktadır. Dahası, istenen konak değerle aynı olmalıdır için de httpd.conf için, genişleme yoluyla, değer ve içinde superglobal. Yine, ben PHP filtre fonksiyonları ile kullanmak istiyorsunuz, ama benim sürüklenme yakalamak.ServerName$_SERVER('SERVER_NAME')$_SERVERINPUT_SERVER

Apaçi sık kullandığını göz önünde bulundurun ServerNameiçinde standart yönlendirmeler : (Örnek, böyle bir URL'ye kapalı eğik çizgiyi bırakarak olarak http://www.foo.com olma http://www.foo.com/ sen olmasa bile,) URL yeniden yazma özelliğini kullanarak.

$_SERVER['SERVER_NAME']Standart olarak kullanıyorum , değil $_SERVER['HTTP_HOST']. Bu konuda ileri geri birçok şey var. $_SERVER['HTTP_HOST']boş olabilir, bu nedenle yukarıdaki genel yöntemim gibi kod kuralları oluşturmak için temel olmamalıdır. Ancak, her ikisinin de ayarlanabilmesi, eşit olacaklarını garanti etmez. Test, emin olmak için en iyi yoldur (Apache sürümü ve PHP sürümü dikkate alınarak).


0

BalusC'nin söylediği gibi SERVER_NAME güvenilir değildir ve apache config'te değiştirilebilir, sunucunun sunucu adı yapılandırması ve sizinle sunucu arasında olabilecek güvenlik duvarı.

Aşağıdaki işlev her zaman bağlantı noktası olmadan gerçek ana bilgisayarı (kullanıcı türü ana bilgisayar) döndürür ve neredeyse güvenilirdir:

function getRealHost(){
   list($realHost,)=explode(':',$_SERVER['HTTP_HOST']);
   return $realHost;
}

0

$ _SERVER ['SERVER_NAME'] web sunucuları yapılandırmanıza dayanmaktadır. $ _SERVER ['HTTP_HOST'] istemcinin isteğine dayanmaktadır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.