PHP में HTTP_HOST और SERVER_NAME में क्या अंतर है?


533

PHP में HTTP_HOSTऔर क्या अंतर है SERVER_NAME?

कहाँ पे:

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

आप कब एक का उपयोग करने पर विचार करेंगे और क्यों?


14
"मैं आमतौर पर HTTP_HOST के लिए जाता हूं, ताकि उपयोगकर्ता उस सटीक होस्ट नाम पर बने रहें जो उन्होंने शुरू किया था। उदाहरण के लिए यदि मेरे पास .com और .org डोमेन पर समान साइट है, तो मैं किसी को .org से नहीं भेजना चाहता।" .com, विशेष रूप से अगर उनके पास लॉगिन टोकन हो सकता है।। - यह और कुछ अन्य रोचक बिंदु stackoverflow.com/questions/1459739/… से
यारिन

5
@ यारिन, के परिणामों को सत्यापितHTTP_HOST करने के लिए मत भूलना । अन्यथा एक हमलावर HTTP के अनुरोध में किसी भी मूल्य को डाल सकता है Host:और सर्वर को स्वीकार कर सकता है।
22

6
शुरुआती: इस प्रश्न का मान आम तौर पर के माध्यम से प्राप्त करने के लिए बात कर रहा है $_SERVER['HTTP_HOST']या$_SERVER['SERVER_NAME']
ग्रेगरी कॉस्मो Haun

जवाबों:


780

HTTP_HOSTसे प्राप्त होता है HTTP अनुरोध हेडर और यह है कि क्या वास्तव में ग्राहक के रूप में अनुरोध की "लक्ष्य मेजबान" का इस्तेमाल किया है। SERVER_NAMEसर्वर config में परिभाषित किया गया है। कौन सा उपयोग करना है यह इस बात पर निर्भर करता है कि आपको इसके लिए क्या चाहिए। आपको अब यह महसूस करना चाहिए कि एक ग्राहक-नियंत्रित मूल्य है जो इस तरह से व्यापार तर्क में उपयोग के लिए विश्वसनीय नहीं हो सकता है और दूसरा सर्वर-नियंत्रित मूल्य है जो अधिक विश्वसनीय है। हालांकि आपको यह सुनिश्चित करने की आवश्यकता है कि प्रश्न में वेबसर्वर SERVER_NAMEसही रूप से कॉन्फ़िगर किया गया है। उदाहरण के तौर पर Apache HTTPD को लेते हुए, इसके प्रलेखन से एक उद्धरण :

यदि कोई ServerNameनिर्दिष्ट नहीं है, तो सर्वर आईपी पते पर एक रिवर्स लुकअप प्रदर्शन करके होस्टनाम को कम करने का प्रयास करता है। यदि कोई पोर्ट निर्दिष्ट नहीं है ServerName, तो सर्वर आने वाले अनुरोध से पोर्ट का उपयोग करेगा। इष्टतम विश्वसनीयता और पूर्वानुमान के लिए, आपको ServerNameनिर्देश का उपयोग करके एक स्पष्ट होस्टनाम और पोर्ट निर्दिष्ट करना चाहिए ।


अपडेट : जाँच के बाद अपने प्रश्न पर पेका का जवाब जो करने के लिए एक लिंक होता है bobince का जवाब है कि PHP हमेशा वापसी होगी HTTP_HOSTके लिए के मूल्य SERVER_NAMEहै, जो 4.x + अपाचे HTTPD कुछ साल से 1.2.x अनुभवों पहले अपने ही पीएचपी के खिलाफ जाता है , मैंने अपने मौजूदा XAMPP वातावरण से Windows XP (PHP 5.2.8 के साथ Apache HTTPD 2.2.1) पर कुछ धूल उड़ा दी, इसे शुरू किया, एक PHP पेज बनाया जो दोनों मानों को प्रिंट करता है, हेडर URLConnectionको संशोधित करने के लिए जावा टेस्ट एप्लिकेशन बनाया। Hostपरीक्षणों ने मुझे सिखाया कि यह वास्तव में (गलत) मामला है।

पहले PHP पर संदेह करने और विषय के संबंध में कुछ PHP बग रिपोर्ट में खुदाई करने के बाद , मुझे पता चला कि समस्या की जड़ उपयोग किए जाने वाले वेब सर्वर में है, कि यह अनुरोध किए Hostजाने पर HTTP हेडर को गलत तरीके से वापस करता है SERVER_NAME। इसलिए मैंने अपाचे HTTPD बग रिपोर्ट में विषय के संबंध में विभिन्न खोजशब्दों का उपयोग किया और अंत में मुझे एक संबंधित बग मिला । यह व्यवहार Apache HTTPD 1.3 के आसपास से पेश किया गया था। आप सेट करने की जरूरत UseCanonicalNameकरने के लिए निर्देश onमें <VirtualHost>की प्रविष्टि ServerNameमें httpd.conf(यह भी के तल पर चेतावनी जाँच दस्तावेज़ !)।

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

इसने मेरे लिए काम किया।

संक्षेप में, SERVER_NAMEअधिक विश्वसनीय है, लेकिन आप सर्वर कॉन्फ़िगरेशन पर निर्भर हैं !


5
ठीक है, यह मेरी समस्या को हल करता है, जो ओपी से संबंधित नहीं है लेकिन प्रासंगिक है। मैं कुछ भी उपयोग करके सुरक्षा मुद्दों के बारे में बहुत चिंतित था जो एक ब्राउज़र आपूर्ति कर सकता था। यह जवाब एक बड़ी मदद थी। इसे एक साथ रखने के लिए समय निकालने के लिए धन्यवाद।
यित्ज़ाक

2
आप यह क्यों कहते हैं कि HTTP_HOST विश्वसनीय नहीं है? हां, यह उपयोगकर्ता द्वारा आपूर्ति की जाती है, लेकिन यदि उपयोगकर्ता कुछ फर्जी मूल्य देता है, तो आपका सर्वर कॉन्फ़िगरेशन स्वचालित रूप से 503 पर वापस आ जाएगा और आपकी PHP स्क्रिप्ट भी नहीं चलेगी!
पचेरियर

1
@ स्पेसर: इस उत्तर को लिखने के समय, यह नहीं किया। उत्तर में संस्करणों का उल्लेख किया गया है। मैं अब PHP के साथ नहीं रखता, इसलिए मैं यह नहीं कह सकता कि क्या यह वास्तव में एक नए संस्करण में बदल गया है।
बालुस

2
विनएक्सपी से अपाचे को ट्रिक करने का एक आसान तरीका यह है कि 'होस्ट्स' फ़ाइल में एक पंक्ति को यह कहते हुए जोड़ा जाए कि सर्वर का आईपी किसी अन्य डोमेन को सौंपा गया है, जैसे: "127.0.0.1 mydomain.com"। मैंने अपने दर्शकों को धोखा देने के लिए एक स्थानीय वेबसाइट दिखाने के लिए बहुत बार इसका उपयोग किया है यह सोचने के लिए कि मैंने इंटरनेट कनेक्शन और साइट को वास्तव में तेजी से लोड किया है। आप दूसरे रास्ते पर जा सकते हैं, और अपाचे को "173.194.41.5 लोकलहोस्ट" के साथ स्थानीय रूप से चलाने के बारे में सोचने के लिए ट्रिक कर सकते हैं, इसलिए आपको कभी भी SERVER_NAME पर पूरी तरह से भरोसा नहीं करना चाहिए जब तक कि आप सुनिश्चित न हों कि आपका Apache अच्छी तरह से कॉन्फ़िगर है।
विसेन्टेर्ररे

1
मैं केवल यह जोड़ना चाहता हूं कि NGINX + PHP-FPM server_nameनिर्देश द्वारा निर्धारित मान लौटाता है । खासकर अगर server_nameसेट नहीं है तो भी _SERVER["SERVER_NAME"]खाली रहेगा।
white_gecko

69

HTTP_HOSTक्लाइंट द्वारा भेजा गया लक्ष्य होस्ट है। यह उपयोगकर्ता द्वारा स्वतंत्र रूप से हेरफेर किया जा सकता है। HTTP_HOSTमान के लिए पूछ कर अपनी साइट पर अनुरोध भेजने में कोई समस्या नहीं है www.stackoverflow.com

SERVER_NAMEसर्वर की VirtualHostपरिभाषा से आता है और इसलिए इसे अधिक विश्वसनीय माना जाता है। हालाँकि, यह आपके वेब सर्वर को कैसे सेट किया जाता है, इससे संबंधित कुछ शर्तों के तहत बाहर से भी हेरफेर किया जा सकता है: यह एसओ का यह प्रश्न देखें जो दोनों विविधताओं के सुरक्षा पहलुओं से संबंधित है।

आपको सुरक्षित होने के लिए किसी पर भी भरोसा नहीं करना चाहिए। उस ने कहा, वास्तव में क्या उपयोग करना है यह उस पर निर्भर करता है जो आप करना चाहते हैं। यदि आप यह निर्धारित करना चाहते हैं कि आपकी स्क्रिप्ट किस डोमेन पर चल रही है, तो आप सुरक्षित HTTP_HOSTरूप से तब तक उपयोग कर सकते हैं जब तक दुर्भावनापूर्ण उपयोगकर्ता से आने वाले अमान्य मान कुछ भी नहीं तोड़ सकते।


8
हां, लेकिन www.stackoverflow.com के HTTP_HOST मूल्य के लिए अनुरोध करने का अनुरोध ज्यादातर HTTP सर्वरों द्वारा अस्वीकार कर दिया जाएगा, ताकि PHP स्क्रिप्ट भी अनुरोध नहीं देख पाएगी!
पचेरियर

2
@ स्पेसर सच है, लेकिन हमेशा नहीं अगर सर्वर ठीक से कॉन्फ़िगर नहीं किया गया है।
पेकका

1
जैसा कि BalusC की पोस्ट में उल्लेख किया गया है, जब आप IP द्वारा Apache virtualhost का उपयोग करते हैं, तो इन दोनों चर में IP (डिफ़ॉल्ट रूप से) होता है, वास्तविक सर्वर नाम नहीं। वास्तविक सर्वर नाम होने के UseCanonicalName onलिए मजबूर SERVER_NAMEकरने के लिए आपको httpd.conf में उपयोग करना होगा।
साइमन ईस्ट

@Pekka 웃, यदि सर्वर ठीक से कॉन्फ़िगर नहीं है, $_SERVER['SERVER_NAME']तो भी काम नहीं करेगा । एक बुरी तरह से कॉन्फ़िगर किया गया सर्वर $_SERVER['SERVER_NAME']क्लाइंट के Host:अनुरोध के मूल्य के आधार पर सेट होगा । दोनों बराबर हैं।
पचेरियर

अच्छा जवाब है, लेकिन मैं वर्चुअल होस्टिंग नहीं मानूंगा।
एंथनी रटलेज

55

जैसा कि मैंने इस उत्तर में उल्लेख किया है , यदि सर्वर 80 के अलावा किसी अन्य पोर्ट पर चलता है (जैसा कि एक डेवलपमेंट / इंट्रानेट मशीन पर आम हो सकता है) HTTP_HOSTमें पोर्ट होता है, जबकि SERVER_NAMEऐसा नहीं होता है।

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

(कम से कम यही मैंने अपाचे पोर्ट-आधारित वर्चुअलहोस्टेस में देखा है)

ध्यान दें कि HTTP_HOSTहै नहीं होते हैं :443जब HTTPS पर चल रहा है (जब तक आप एक गैर मानक पोर्ट, जो मैं परीक्षण नहीं किया पर चल रहे हैं)।

जैसा कि अन्य ने उल्लेख किया है, दोनों IPv6 का उपयोग करते समय भिन्न होते हैं:

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

2
वे इस कपटपूर्ण व्यवहार को कब ठीक करेंगे?
पचेरियर

27

कृपया ध्यान दें कि यदि आप IPv6 का उपयोग करना चाहते हैं, तो आप शायद HTTP_HOSTइसके बजाय उपयोग करना चाहते हैं SERVER_NAME। यदि आप http://[::1]/पर्यावरण में प्रवेश करते हैं तो चर निम्नलिखित होंगे:

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

इसका मतलब है, कि यदि आप उदाहरण के लिए एक mod_rewrite करते हैं, तो आपको एक बुरा परिणाम मिल सकता है। SSL पुनर्निर्देशित के लिए उदाहरण:

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

यह केवल तब लागू होता है जब आप होस्टनाम के बिना सर्वर तक पहुँचते हैं।


1
SiteGround, उनके इनहाउस http में https रीडायरेक्ट कोड, का उपयोगhttps://%{SERVER_NAME}%{REQUEST_URI}
IXN

6

यदि आप एक server.php के माध्यम से या जो कुछ भी जांचना चाहते हैं, आप इसे निम्नलिखित के साथ कॉल करना चाहते हैं:

<?php
    phpinfo(INFO_VARIABLES);
?>

या

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

    print_r($_SERVER);
?>

फिर अपनी साइट के लिए सभी मान्य URL तक पहुँचें और अंतर देखें।


5

निर्भर करता है कि मुझे क्या पता लगाना है। SERVER_NAME सर्वर का होस्ट नाम है, जबकि HTTP_HOST वह वर्चुअल होस्ट है जिससे क्लाइंट जुड़ा हुआ है।


4
बिल्कुल सही रॉलैंड नहीं है, SERVER_NAMEआमतौर पर वर्चुअलबॉस्ट का नाम है, न कि सर्वर का। और अपाचे में, SERVER_NAMEअक्सर उसी मूल्य के साथ आबादी होती है जैसे HTTP_HOST(BalusC का उत्तर देखें)।
साइमन ईस्ट

1
@Simon, चूंकि अधिकांश होस्ट अब VirtualHost हैं, तो "सर्वर स्वयं" के नाम से आपका क्या मतलब होगा?
पचेरियर

यदि आप एक वेबसाइट के साथ एक वर्चुअल प्राइवेट सर्वर (VPS) चला रहे हैं, तो आपको यह मानने की आवश्यकता नहीं है कि SERVER_NAMEवर्चुअल होस्ट पर लागू होता है। हालाँकि, कोई अभी भी एक साइट के लिए वर्चुअल होस्ट सेटअप का उपयोग कर सकता है। कई लोग साझा होस्टिंग का उपयोग करते हैं, इसलिए मैं आपकी बात देखता हूं।
एंथनी रटलेज

2

मुझे यह समझने में थोड़ा समय लगा कि meant SERVER_NAMEअधिक विश्वसनीय ’ लोगों का क्या मतलब है । मैं एक साझा सर्वर का उपयोग करता हूं और वर्चुअल होस्ट निर्देशों तक पहुंच नहीं है। इसलिए, मैं mod_rewrite का उपयोग अलग-अलग निर्देशिकाओं के लिए अलग- .htaccess अलग मैप करने के लिए करता हूं HTTP_HOST। उस मामले में, यह वह है HTTP_HOSTजो सार्थक है।

स्थिति समान है यदि कोई नाम-आधारित वर्चुअल होस्ट का उपयोग करता है: ServerNameएक वर्चुअल होस्ट के भीतर निर्देश बस यह कहता है कि कौन सा होस्टनाम इस वर्चुअल होस्ट पर मैप किया जाएगा। लब्बोलुआब यह है कि, दोनों मामलों में, क्लाइंट द्वारा अनुरोध के दौरान प्रदान किए गए होस्टनाम HTTP_HOSTको सर्वर के भीतर एक नाम के साथ मिलान किया जाना चाहिए, जो स्वयं एक निर्देशिका में मैप किया गया है। मैपिंग वर्चुअल होस्ट निर्देशों के साथ की गई है या htaccess mod_rewrite नियमों के साथ यहां माध्यमिक है। इन मामलों में, HTTP_HOSTजैसा होगा वैसा ही होगा SERVER_NAME। मुझे खुशी है कि अपाचे को इस तरह से कॉन्फ़िगर किया गया है।

हालांकि, आईपी-आधारित वर्चुअल होस्ट के साथ स्थिति अलग है। इस मामले में और केवल इस मामले में, SERVER_NAMEऔर HTTP_HOSTअलग-अलग हो सकते हैं, क्योंकि अब क्लाइंट आईपी द्वारा सर्वर का चयन करता है, नाम से नहीं। वास्तव में, विशेष कॉन्फ़िगरेशन हो सकते हैं जहां यह महत्वपूर्ण है।

इसलिए, अब से, मैं उपयोग करूंगा SERVER_NAME, बस अगर मेरा कोड इन विशेष कॉन्फ़िगरेशन में पोर्ट किया गया है।


2

मान लें कि एक साधारण सेटअप है (CentOS 7, Apache 2.4.x, और PHP 5.6.20) और केवल एक वेबसाइट (वर्चुअल होस्टिंग नहीं मान रहा है) ...

PHP के अर्थ में, httpd.conf में आपके अपाचे कॉन्फ़िगरेशन ( निर्देश के साथ ) के आधार पर सुपरग्लोबल $_SERVER['SERVER_NAME']में एक तत्व PHP रजिस्टर है (इसे शामिल वर्चुअल होस्ट कॉन्फ़िगरेशन फ़ाइल से, जो भी हो, आदि ...)। HTTP_HOST HTTP हेडर से लिया गया है । इसे यूजर इनपुट मानें। उपयोग करने से पहले फ़िल्टर और मान्य करें।$_SERVER**ServerName**UseCanonicalName Onhost

यहाँ एक उदाहरण है जहाँ मैं $_SERVER['SERVER_NAME']तुलना के आधार के रूप में उपयोग करता हूँ । निम्नलिखित विधि एक ठोस बच्चे वर्ग से है जिसे मैंने नाम दिया है ServerValidator(बच्चे का Validator)। ServerValidatorउपयोग करने से पहले $ _SERVER में छह या सात तत्वों की जाँच करता है।

यह निर्धारित करने में कि HTTP अनुरोध POST है, मैं इस पद्धति का उपयोग करता हूं।

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

जब तक इस विधि को कहा जाता है, तब तक प्रासंगिक $ _SERVER तत्वों के सभी फ़िल्टरिंग और सत्यापन घटित हो जाते हैं (और प्रासंगिक गुण सेट होते हैं)।

रेखा ...

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

... जाँचता है कि $_SERVER['HTTP_HOST']मूल्य (अंततः अनुरोधित hostHTTP हेडर से प्राप्त होता है ) मेल खाता है $_SERVER['SERVER_NAME']

अब, मैं superglobal बात का उपयोग कर रहा मेरी उदाहरण समझाने के लिए है, लेकिन वह यह है कि सिर्फ इसलिए कि कुछ लोगों के साथ अपरिचित हैं INPUT_GET, INPUT_POSTऔर INPUT_SERVERसंबंध में करने के लिए filter_input_array()

लब्बोलुआब यह है, मैं अपने सर्वर पर POST अनुरोधों को संभाल नहीं जब तक सभी चार शर्तों को पूरा कर रहे हैं। इसलिए, POST अनुरोधों के संदर्भ में, HTTP hostहैडर प्रदान करने में विफलता (पहले के लिए परीक्षण की गई उपस्थिति) सख्त HTTP 1.0 ब्राउज़रों के लिए कयामत को बढ़ाती है। इसके अलावा, अनुरोध किया मेजबान मूल्य से मेल खाना चाहिए के लिए में httpd.conf , मूल्य के लिए, और, विस्तार से में superglobal। फिर से, मैं PHP फ़िल्टर फ़ंक्शंस के साथ उपयोग करूंगा , लेकिन आप मेरे बहाव को पकड़ लेंगे।ServerName$_SERVER('SERVER_NAME')$_SERVERINPUT_SERVER

ध्यान रखें कि अपाचे अक्सर उपयोग करता ServerNameमें मानक रीडायरेक्ट (जैसे कि URL बंद स्लैश छोड़ने के रूप में: उदाहरण के लिए, http://www.foo.com बनने http://www.foo.com/ ), भले ही आप नहीं कर रहे हैं URL पुनर्लेखन का उपयोग करना।

मैं $_SERVER['SERVER_NAME']मानक के रूप में उपयोग करता हूं , नहीं $_SERVER['HTTP_HOST']। इस मुद्दे पर बहुत कुछ आगे और पीछे है। $_SERVER['HTTP_HOST']खाली हो सकता है, इसलिए यह ऊपर मेरी सार्वजनिक पद्धति जैसे कोड सम्मेलनों को बनाने का आधार नहीं होना चाहिए। लेकिन, सिर्फ इसलिए कि दोनों सेट हो सकते हैं गारंटी नहीं है कि वे समान होंगे। परीक्षण सुनिश्चित करने के लिए सबसे अच्छा तरीका है (अपाचे संस्करण और PHP संस्करण को ध्यान में रखते हुए)।


0

जैसा कि balusC ने कहा कि SERVER_NAME विश्वसनीय नहीं है और इसे अपाचे कॉन्फिगर, सर्वर के सर्वर नेम और फ़ायरवॉल के नाम से बदला जा सकता है जो आपके और सर्वर के बीच हो सकता है।

निम्नलिखित फ़ंक्शन हमेशा पोर्ट के बिना वास्तविक होस्ट (उपयोगकर्ता टाइप किए गए होस्ट) को वापस करते हैं और यह लगभग विश्वसनीय है:

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

0

$ _SERVER ['SERVER_NAME'] आपके वेब सर्वर कॉन्फ़िगरेशन पर आधारित है। $ _SERVER ['HTTP_HOST'] ग्राहक के अनुरोध पर आधारित है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.