سؤال

متى تفكر في استخدام واحد على الآخر ولماذا؟

هل كانت مفيدة؟

المحلول

ال HTTP_HOST تم الحصول عليها من HTTP طلب طلب وهذا ما يستخدمه العميل بالفعل كمضيف مستهدف "للطلب. ال SERVER_NAME تم تعريفه في تكوين الخادم. أي واحد لاستخدامه يعتمد على ما تحتاج إليه. ومع ذلك ، يجب عليك الآن أن تدرك أن هذه القيمة هي قيمة يتم التحكم فيها عن العميل والتي قد لا تكون موثوقة للاستخدام في منطق الأعمال والآخر هو قيمة يتم التحكم فيها عن الخادم والتي تكون أكثر موثوقية. ومع ذلك ، تحتاج إلى التأكد من أن خادم الويب المعني لديه SERVER_NAME تم تكوينها بشكل صحيح. أخذ Apache HTTPD كمثال ، إليك مستخلص من وثائقها:

إذا كان لا ServerName تم تحديده ، ثم يحاول الخادم استنتاج اسم المضيف عن طريق إجراء بحث عكسي على عنوان IP. إذا لم يتم تحديد منفذ في ServerName, ، سيستخدم الخادم المنفذ من الطلب الوارد. للحصول على الموثوقية الأمثل وقابلية التنبؤ ، يجب عليك تحديد اسم مضيف وموانئ صريحة باستخدام ServerName التوجيه.


تحديث: بعد الفحص إجابة بيكا على سؤالك الذي يحتوي على رابط إلى إجابة بوبنس سيعود هذا PHP دائمًا HTTP_HOSTقيمة ل SERVER_NAME, ، الذي يتعارض مع تجارب PHP 4.x + Apache HTTPD 1.2.x منذ عامين ، فجرت بعض الغبار من بيئة XAMPP الحالية على Windows XP (Apache HTTPD 2.2.1 مع PHP 5.2.8) ، بدأت قامت بإنشاء صفحة PHP التي تطبع كلتا القيمتين ، وإنشاء تطبيق اختبار Java باستخدام URLConnection لتعديل Host علمتني الرأس والاختبارات أن هذا بالفعل (بشكل غير صحيح) هو القضية.

بعد الشك الأول في PHP والحفر في بعض تقارير علة PHP فيما يتعلق بالموضوع ، علمت أن جذر المشكلة في خادم الويب المستخدم ، وأنه قد تم إرجاعه بشكل غير صحيح http Host رأس متى SERVER_NAME وطلب. لذلك حفرت في تقارير أخطاء Apache HTTPD استخدام كلمات رئيسية مختلفة بخصوص الموضوع ووجدت أخيرًا ملف علة ذات صلة. تم تقديم هذا السلوك منذ حول Apache HTTPD 1.3. تحتاج إلى ضبط UseCanonicalName التوجيه ل on في ال <VirtualHost> دخول ServerName في httpd.conf (تحقق أيضًا من التحذير في أسفل المستند!).

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

هذا عمل بالنسبة لي.

ملخصت ، SERVER_NAME أكثر موثوقية ، لكنك يعتمد على تكوين الخادم!

نصائح أخرى

HTTP_HOST هو المضيف الهدف الذي أرسله العميل. يمكن معالجتها بحرية من قبل المستخدم. لا توجد مشكلة في إرسال طلب إلى موقعك يطلب HTTP_HOST قيمة ال www.stackoverflow.com.

SERVER_NAME يأتي من الخادم VirtualHost التعريف وبالتالي يعتبر أكثر موثوقية. ومع ذلك ، يمكن معالجتها أيضًا من الخارج في ظل ظروف معينة تتعلق بكيفية إعداد خادم الويب الخاص بك: انظر هذا هذا السؤال جدا الذي يتناول الجوانب الأمنية لكلا الاختلافات.

يجب ألا تعتمد على أن تكون آمنة. ومع ذلك ، فإن ما يجب استخدامه يعتمد حقًا على ما تريد القيام به. إذا كنت ترغب في تحديد المجال الذي يعمل عليه البرنامج النصي ، يمكنك استخدامه بأمان HTTP_HOST طالما أن القيم غير الصالحة القادمة من مستخدم ضار لا يمكنها كسر أي شيء.

كما ذكرت في هذا الجواب, ، إذا كان الخادم يعمل على منفذ آخر غير 80 (كما قد يكون شائعًا في آلة التطوير/الإنترانت) ثم HTTP_HOST يحتوي على المنفذ ، بينما SERVER_NAME لا.

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

(على الأقل هذا ما لاحظته في VirtualHosts المستندة إلى منفذ Apache)

لاحظ أن HTTP_HOST يفعل ليس يحتوي :443 عند تشغيل HTTPS (ما لم تكن تعمل على منفذ غير قياسي ، لم أختبره).

كما لاحظ آخرون ، يختلف الاثنان أيضًا عند استخدام IPv6:

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

يرجى ملاحظة أنه إذا كنت تريد استخدام 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}/

ينطبق هذا فقط إذا قمت بالوصول إلى الخادم بدون اسم مضيف.

إذا كنت ترغب في التحقق من خلال خادم.

<?php

phpinfo(INFO_VARIABLES);

?>

أو

<?php

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

print_r($_SERVER);

?>

ثم قم بالوصول إليه مع جميع عناوين URL الصالحة لموقعك وتحقق من الفرق.

يعتمد على ما أريد معرفة ذلك. Server_name هو اسم المضيف للخادم ، في حين أن http_host هو المضيف الظاهري الذي يتصل به العميل.

استغرق الأمر مني بعض الوقت لفهم ما يعنيه الناس "SERVER_NAME أكثر موثوقية. أستخدم خادمًا مشتركًا وليس لديه إمكانية الوصول إلى توجيهات المضيف الظاهري. لذلك ، أستخدم mod_rewrite في .htaccess لرسم خريطة مختلفة HTTP_HOSTS إلى دلائل مختلفة. في هذه الحالة ، هو كذلك HTTP_HOST هذا مفيد.

الموقف متشابه إذا كان المرء يستخدم المضيفين الظاهري القائم على الاسم: ServerName توجيه ضمن مضيف افتراضي يقول ببساطة أي اسم المضيف سيتم تعيينه لهذا المضيف الافتراضي. خلاصة القول هي أنه في كلتا الحالتين ، اسم المضيف الذي يقدمه العميل أثناء الطلب (HTTP_HOST) ، يجب مطابقة اسم داخل الخادم ، والذي يتم تعيينه نفسه إلى دليل. ما إذا كان التعيين يتم بتوجيهات المضيف الظاهري أو باستخدام قواعد htaccess mod_rewrite ثانوية هنا. في هذه الحالات، HTTP_HOST سيكون هو نفسه SERVER_NAME. أنا سعيد لأن Apache تم تكوينه بهذه الطريقة.

ومع ذلك ، فإن الموقف مختلف مع المضيفين الافتراضيين القائم على IP. في هذه الحالة وفقط في هذه الحالة ، SERVER_NAME و HTTP_HOST يمكن أن يكون مختلفًا ، لأن العميل يحدد الآن الخادم بواسطة IP ، وليس بالاسم. في الواقع ، قد تكون هناك تكوينات خاصة حيث هذا أمر مهم.

لذا ، بدءًا من الآن ، سأستخدم SERVER_NAME, ، فقط في حالة نقل الكود الخاص بي في هذه التكوينات الخاصة.

على افتراض أن لدى أحدهم إعدادًا بسيطًا (Centos 7 و Apache 2.4.x و PHP 5.6.20) وموقع ويب واحد فقط (لا يفترض استضافة افتراضية) ...

بمعنى PHP ، $_SERVER['SERVER_NAME'] هو عنصر PHP سجلات في $_SERVER SuperGlobal استنادًا إلى تكوين Apache الخاص بك (**ServerName** التوجيه مع UseCanonicalName On ) في httpd.conf (سواء كان ذلك من ملف تكوين المضيف الظاهري ، أيا كان ، إلخ ...). http_host مشتق من HTTP host رأس. تعامل مع هذا كمدخل المستخدم. تصفية والتحقق من صحة قبل استخدام.

إليك مثال على المكان الذي أستخدمه $_SERVER['SERVER_NAME'] كأساس للمقارنة. الطريقة التالية هي من فئة طفل ملموسة قمت بتسميتها ServerValidator (طفل Validator). ServerValidator يتحقق ستة أو سبعة عناصر في $ _server قبل استخدامها.

عند تحديد ما إذا كان طلب HTTP هو النشر ، أستخدم هذه الطريقة.

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'] القيمة (مشتقة في النهاية من المطلوبة host رأس HTTP) مباريات $_SERVER['SERVER_NAME'].

الآن ، أنا أستخدم Superglobal تحدث لشرح مثالي ، لكن هذا فقط لأن بعض الناس غير مألوفين INPUT_GET, INPUT_POST, ، و INPUT_SERVER في ما يخص filter_input_array().

خلاصة القول هي أنني لا أتعامل مع الطلبات على الخادم الخاص بي إلا إذا الكل تم استيفاء أربعة شروط. وبالتالي ، من حيث طلبات النشر ، الفشل في تقديم HTTP host نوبات الرأس (تم اختبارها في وقت سابق) الموت لصيامة HTTP 1.0 المتصفحات. علاوة على ذلك ، فإن المضيف المطلوب يجب أن تطابق القيمة ل ServerName في ال httpd.conf, و ، بالتمديد ، القيمة ل $_SERVER('SERVER_NAME') في ال $_SERVER superglobal. مرة أخرى ، سأستخدم INPUT_SERVER مع وظائف مرشح PHP ، لكنك تمسك بالانجراف.

ضع في اعتبارك أن Apache يستخدم بشكل متكرر ServerName في إعادة التوجيه القياسية (مثل ترك القطع المدمرة عن عنوان URL: مثال ، http://www.foo.com تصبح http://www.foo.com/) ، حتى لو كنت لا تستخدم إعادة كتابة عنوان URL.

أنا أستعمل $_SERVER['SERVER_NAME'] كمعيار ، وليس $_SERVER['HTTP_HOST']. هناك الكثير من ذهابًا وإيابًا حول هذه القضية. $_SERVER['HTTP_HOST'] يمكن أن يكون فارغًا ، لذلك لا ينبغي أن يكون هذا هو الأساس لإنشاء اتفاقيات رمز مثل طريقتي العامة أعلاه. ولكن ، لمجرد أن كلاهما قد لا يضمن أنه سيكون مساوًا. الاختبار هو أفضل طريقة لمعرفة بالتأكيد (مع الأخذ في الاعتبار إصدار Apache وإصدار PHP).

كما قال Balusc Server_name غير موثوق به ويمكن تغييره في Apache Config ، تكوين اسم الخادم من الخادم وجدار الحماية الذي يمكن أن يكون بينك وبين Server.

تتبع الوظيفة دائمًا إرجاع HEAL HOST (المضيف المكتوب للمستخدم) بدون منفذ وهو موثوق به تقريبًا:

function getRealHost(){
   list($realHost,)=explode(':',$_SERVER['HTTP_HOST']);
   return $realHost;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top