[php] PHP에서 HTTP_HOST와 SERVER_NAME의 차이점은 무엇입니까?

PHP HTTP_HOSTSERVER_NAMEPHP 의 차이점은 무엇입니까 ?

어디:

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

언제 다른 것을 사용하는 것이 좋을까요?



답변

HTTP_HOST으로부터 얻을 수 HTTP 요청 헤더 와이 클라이언트가 실제로 요청 “대상 호스트”로 사용되는 것입니다. 은 SERVER_NAME서버 설정에 정의되어 있습니다. 어떤 것을 사용해야하는지에 따라 다릅니다. 그러나 이제는 하나가 비즈니스 제어에 사용하기에 신뢰할 수없는 클라이언트 제어 값이고 다른 하나는보다 안정적인 서버 제어 값임을 인식해야합니다. 그러나 해당 웹 서버가 SERVER_NAME올바르게 구성 되어 있는지 확인해야 합니다. Apache HTTPD를 예로 들어, 다음 은 문서 에서 추출한 것입니다 .

no ServerName를 지정하면 서버는 IP 주소에서 역방향 조회를 수행하여 호스트 이름을 추론하려고 시도합니다. 에 포트가 지정되어 있지 않으면 ServerName서버는 들어오는 요청의 포트를 사용합니다. 최적의 안정성과 예측 성을 위해서는 ServerName지시문을 사용하여 명시적인 호스트 이름과 포트를 지정해야 합니다.


업데이트 : 귀하의 질문에 Pekka의 답변을 확인한 후 PHP가 항상 의 가치를 반환한다는 bobince의 답변에 대한 링크가 포함되어 있습니다 .2 년 전의 내 PHP 4.x + Apache HTTPD 1.2.x 경험에 반합니다. , 나는 Windows XP (PHP 5.2.8의 Apache HTTPD 2.2.1)에서 현재 XAMPP 환경에서 약간의 먼지를 날려 시작하여 두 값을 인쇄하는 PHP 페이지를 만들고 헤더 를 수정하는 데 사용하는 Java 테스트 응용 프로그램을 만들었습니다. 테스트는 이것이 실제로 (잘못된) 사례라고 가르쳐주었습니다.HTTP_HOSTSERVER_NAMEURLConnectionHost

먼저 PHP를 의심 하고 주제에 관한 일부 PHP 버그 보고서 를 파고 Host들었을 때 문제의 근본이 웹 서버에서 사용되어 SERVER_NAME요청 시 HTTP 헤더를 잘못 반환한다는 것을 알았습니다 . 그래서 주제에 관한 다양한 키워드 를 사용하여 Apache HTTPD 버그 보고서 를 파헤 쳤고 마침내 관련 버그를 발견했습니다 . 이 동작은 Apache HTTPD 1.3부터 ​​도입되었습니다. 당신은 설정에 필요 에 지시 에서 의 항목 에서 (또한 하단의 경고 확인 문서를 !).UseCanonicalNameon<VirtualHost>ServerNamehttpd.conf

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

이것은 나를 위해 일했습니다.

요약하면 SERVER_NAME더 안정적이지만 서버 구성에 의존 합니다!


답변

HTTP_HOST클라이언트가 보낸 대상 호스트입니다. 사용자가 자유롭게 조작 할 수 있습니다. 사이트에 HTTP_HOST값을 요청하는 요청을 보내는 것은 문제가되지 않습니다 www.stackoverflow.com.

SERVER_NAME서버의 VirtualHost정의 에서 나오므로보다 안정적인 것으로 간주됩니다. 그러나 웹 서버 설정 방법과 관련된 특정 조건 하에서 외부에서 조작 할 수도 있습니다 .이 두 가지 변형의 보안 측면을 다루는 이 SO 질문 을 참조하십시오 .

안전하기 위해 의존해서는 안됩니다. 즉, 사용하는 것은 실제로 원하는 일에 달려 있습니다. 스크립트가 실행중인 도메인을 확인하려는 경우 HTTP_HOST악의적 인 사용자가 제공 한 잘못된 값이 아무 것도 깨지지 않는 한 안전하게 사용할 수 있습니다.


답변

이 답변 에서 언급했듯이 서버가 80 이외의 포트에서 실행되는 경우 (개발 / 인트라넷 컴퓨터에서 일반적 일 수 있음) HTTP_HOST포트가 포함되어 있지만 SERVER_NAME그렇지 않습니다.

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

(적어도 아파치 포트 기반 가상 호스트에서 눈치 채 셨을 것입니다)

참고 HTTP_HOST않습니다 하지 포함 :443HTTPS에서 실행되는 경우 (당신은 내가 테스트하지 않은 비표준 포트에서 실행하지 않는 한).

다른 사람들이 지적했듯이 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}/

호스트 이름없이 서버에 액세스하는 경우에만 적용됩니다.


답변

server.php 등을 통해 확인하려면 다음과 같이 호출하십시오.

<?php
    phpinfo(INFO_VARIABLES);
?>

또는

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

    print_r($_SERVER);
?>

그런 다음 사이트에 유효한 모든 URL로 액세스하여 차이점을 확인하십시오.


답변

내가 찾고 싶은 것에 달려 있습니다. SERVER_NAME은 서버의 호스트 이름이며 HTTP_HOST는 클라이언트가 연결된 가상 호스트입니다.


답변

사람들이 ‘ SERVER_NAME신뢰할 수있는 것’의 의미를 이해하는 데 시간이 걸렸습니다 . 공유 서버를 사용하고 가상 호스트 지시문에 액세스 할 수 없습니다. 그래서 mod_rewrite를 사용 하여 다른 디렉토리를 다른 디렉토리 .htaccess 에 매핑 HTTP_HOST합니다. 이 경우 HTTP_HOST의미가 있습니다.

이름 기반 가상 호스트를 사용하는 경우와 비슷한 상황입니다. ServerName 내의 지시문은이 가상 호스트에 매핑 될 호스트 이름 만 나타냅니다. 결론적으로, 두 경우 모두 요청 ( HTTP_HOST) 동안 클라이언트가 제공 한 호스트 이름은 서버 내 이름과 일치해야하며,이 이름은 자체적으로 디렉토리에 매핑됩니다. 매핑이 가상 호스트 지시어 또는 htaccess mod_rewrite 규칙으로 수행되는지 여부는 부차적입니다. 이 경우 HTTP_HOST와 같습니다 SERVER_NAME. 아파치가 그런 식으로 구성되어 기쁘다.

그러나 상황은 IP 기반 가상 호스트와 다릅니다. 이 경우에만이 경우, SERVER_NAME그리고 HTTP_HOST지금은 클라이언트가 아니라 이름의 IP에서 서버를 선택하기 때문에 다를 수 있습니다. 실제로 이것이 중요한 특별한 구성이있을 수 있습니다.

따라서 지금부터는 SERVER_NAME코드가 이러한 특수 구성으로 이식되는 경우를 대비하여을 사용합니다.