$_SERVER['HTTP_HOST']值异常,跨域cURL请求拦截失效排查
问题分析与解决方案
首先得纠正你一个核心误解:$_SERVER['HTTP_HOST'] 不是用来获取请求来源域名的,它代表的是客户端请求中携带的Host头部——也就是你请求的目标域名(这里应该是domain4.com)。你看到它显示domain1.com,说明你的Apache配置或者curl请求存在问题,我们先解决这个,再处理拦截请求的需求。
一、为什么$_SERVER['HTTP_HOST']总是显示domain1.com?
最可能的原因是你的Apache虚拟主机配置有误:domain4.com没有被配置为独立的虚拟主机,而是和domain1.com共用了同一个默认虚拟主机,且该主机的ServerName被设置为domain1.com。
修复步骤:
- 打开Apache的虚拟主机配置目录(Ubuntu 16.04下是
/etc/apache2/sites-available/) - 为
domain4.com创建独立的配置文件,比如domain4.conf:
<VirtualHost *:80> ServerName domain4.com ServerAlias www.domain4.com DocumentRoot /var/www/domain4 # 替换为你的domain4网站根目录 ErrorLog ${APACHE_LOG_DIR}/domain4-error.log CustomLog ${APACHE_LOG_DIR}/domain4-access.log combined </VirtualHost>
- 启用该配置并重启Apache:
sudo a2ensite domain4.conf sudo service apache2 restart
完成后,再用curl请求domain4.com,$_SERVER['HTTP_HOST']就会正确显示domain4.com了。
二、如何正确拦截来自domain1/2/3的请求?
要识别请求的来源,不能用HTTP_HOST,根据需求的安全性要求,你可以选择以下几种方案:
方案1:检查Referer头部(适合非高安全场景)
$_SERVER['HTTP_REFERER']会记录请求的来源页面URL,但注意:curl默认不会发送这个头部,需要手动添加,且该头部可以被伪造。
- 在domain1/2/3的curl代码中添加Referer:
curl_setopt($ch, CURLOPT_REFERER, "http://domain1.com/"); // 对应各自的域名
- 在domain4.com的代码中验证:
$blacklisted_domains = ["domain1.com", "domain2.com", "domain3.com"]; $referer = $_SERVER['HTTP_REFERER'] ?? ''; $is_blacklisted = false; foreach ($blacklisted_domains as $domain) { if (strpos($referer, $domain) !== false) { $is_blacklisted = true; break; } } if ($is_blacklisted) { http_response_code(403); exit("Forbidden: Requests from this domain are blocked"); }
方案2:验证来源IP(更可靠)
如果domain1/2/3的服务器有固定公网IP,直接通过IP拦截是更可靠的方式。
- 在domain4.com的PHP代码中检查:
$blacklisted_ips = ["192.168.1.100", "192.168.1.101"]; // 替换为domain1/2/3的服务器IP $client_ip = $_SERVER['REMOTE_ADDR']; if (in_array($client_ip, $blacklisted_ips)) { http_response_code(403); exit("Forbidden: Requests from this IP are blocked"); }
或者你也可以直接在Apache配置中拦截,更高效:
在domain4.conf中添加:
<Directory /var/www/domain4> Require all granted Require not ip 192.168.1.100 192.168.1.101 </Directory>
然后重启Apache即可。
方案3:使用API密钥(最安全,适合内部服务)
如果是你自己控制的服务之间调用,用密钥验证是最安全的方式,不受域名/IP变化的影响。
- 在domain1/2/3的curl请求中添加密钥参数:
$post_data = http_build_query([ 'msg' => $msg, 'api_key' => 'your-strong-secret-key-here' ]); curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
- 在domain4.com的代码中验证密钥:
$valid_api_key = 'your-strong-secret-key-here'; if (!isset($_POST['api_key']) || $_POST['api_key'] !== $valid_api_key) { http_response_code(403); exit("Forbidden: Invalid API key"); }
内容的提问来源于stack exchange,提问作者Rav_g
相关产品推荐
相关产品推荐

