场景:我正在使用一些PHP工作在Apache Web服务器上.我将浏览器指向https://my.example.com/test.php,其中包含以下代码行:
<pre>
<?php
print_r($_SERVER);
?>
</pre>
Run Code Online (Sandbox Code Playgroud)
为SERVER_PORT打印的值是80,而不是443.但是,如果我去https://my.example.com:80/test.php网络服务器(Apache)barfs(连接到my.example.com:80时发生错误.SSL收到的记录超过了最大允许长度.错误代码:ssl_error_rx_record_too_long).如果我转到https://my.example.com:443/test.php,那么URL会重定向到https://my.example.com/test.php,没有任何错误或问题,除了我的PHP打印出来服务器端口是80而不是443.
这是conf.d/ssl.conf文件中的相关部分(我删除了我认为无关的指令,并用IP_ADDRESS替换了实际的IP地址):
Listen IP_ADDRESS:443
<VirtualHost *:443>
ServerName my.example.com
ServerAlias my
DocumentRoot "/path/to/document_root/htdocs"
Options +Indexes
</VirtualHost>
Run Code Online (Sandbox Code Playgroud)
以下是$ _SERVER变量的完整打印(我的服务器详细信息已编辑/更改为匿名示例):
Array
(
[HTTP_HOST] => my.example.com
[HTTP_USER_AGENT] => Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.11) Gecko/20101012 Firefox/3.6.11
[HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
[HTTP_ACCEPT_LANGUAGE] => en-us,en;q=0.5
[HTTP_ACCEPT_ENCODING] => gzip,deflate
[HTTP_ACCEPT_CHARSET] => ISO-8859-1,utf-8;q=0.7,*;q=0.7
[HTTP_KEEP_ALIVE] => 115
[HTTP_CONNECTION] => keep-alive
[HTTP_COOKIE] => PHPSESSID=randomstring_yes_I'm_that_paranoid
[PATH] => /sbin:/usr/sbin:/bin:/usr/bin
[SERVER_SIGNATURE] =>
Apache/2.2.3 (Red Hat) Server at my.example.com Port 80
[SERVER_SOFTWARE] => Apache/2.2.3 (Red Hat)
[SERVER_NAME] => my.example.com
[SERVER_ADDR] => IP_ADDRESS_1
[SERVER_PORT] => 80
[REMOTE_ADDR] => IP_ADDRESS_2
[DOCUMENT_ROOT] => /path/to/document_root/htdocs
[SERVER_ADMIN] => admin@example.com
[SCRIPT_FILENAME] => /path/to/document_root/htdocs/test.php
[REMOTE_PORT] => 49178
[GATEWAY_INTERFACE] => CGI/1.1
[SERVER_PROTOCOL] => HTTP/1.1
[REQUEST_METHOD] => GET
[QUERY_STRING] =>
[REQUEST_URI] => /test.php
[SCRIPT_NAME] => /test.php
[PHP_SELF] => /test.php
[REQUEST_TIME] => 1292273758
)
Run Code Online (Sandbox Code Playgroud)
如您所见,SERVER_PORT为80且未设置$ _SERVER ['HTTPS'].根据PHP文档,我认为如果通过HTTPS访问PHP脚本(我正在做的事情),它应该被设置为非空值.
知道发生了什么事吗?我只是网络开发人员 - 我不管理这个服务器,但我的服务器管理员告诉我一切正常,但我想知道为什么$ _SERVER ['SERVER_PORT']在查看HTTPS URL时返回80而不是443.
编辑:我编辑了上面的例子来说明打印出整个$ _SERVER变量的结果.
编辑2:按照以下评论中的建议尝试https://my.example.com:443/test.php做同样的事情 - SERVER_PORT是80并且未设置HTTPS(特别是尝试将此URL重定向到https:// my.example.com/test.php).
编辑3:好的,我发布了我认为是下面的答案(TL; DR:在VirtualHost指令中移动SSL指令并更改该指令以使用它的IP地址引用我的站点而不是通配符似乎有解决了这个问题).
Ste*_*iov 15
我刚刚遇到了同样的问题,因为我遇到的一些代码掩盖了同样的问题.
我对这个问题的诊断如下:这是Apache 2.0中的一个变化的怪癖.Port指令不再是httpd.conf指令的一部分,基本上在ServerName和Listen指令之间分开.
所以我的apache httpd.conf(Apache 2.2.23)有这些条目
ServerName myservername.com
Listen: 5150
Run Code Online (Sandbox Code Playgroud)
然而,PHP $ _SERVER ['SERVER_PORT']正在向端口5150上发出的所有请求返回80.
因此仔细考虑了Apache文档,我发现了一个关于Port是一个弃用的指令和ServerName包含它的一个小窍门.
我设置我的servername指令如下
ServerName myservername.com:5150
UseCanonicalName On
Listen 5150
Run Code Online (Sandbox Code Playgroud)
突然,php脚本正在做正确的事情,报告_SERVER ['SERVER_PORT']为5150.
或者你的httpd.conf可以阅读
ServerName myservername.com
UseCanonicalName Off
Listen 5150
Run Code Online (Sandbox Code Playgroud)
然后我挖掘了php(5.3.20)源代码和apache源代码,直到我找到了行为的来源.
在dirOfApacheSource/server/core.c
查看函数时
,行为根植于(至少对于已缓存的2.2.23源代码)
AP_DECLARE(apr_port_t) ap_get_server_port(const request_rec *r)
在这里,您将看到如果您的httpd UseCanonicalName指令设置为"On",则端口将被解析出ServerName指令.当ServerName指令不是ServerName myserver.com:myport编号的形式时,案例代码将获取请求对象的ap_default_port(由apache人员将其默认设置为80).
如果您需要将该端口显式添加到httpd.conf中的ServerName指令,那么您的另一个选择是将UseCanonicalName设置为"Off",这会强制server/core.c中的代码将URI请求解析为提取服务器名称和端口.
其中六个,另外六个,调整你的apache httpd.conf文件,你很快就会看到预期的结果.
我似乎记得几年前升级 apache 时发生过这种情况。它最终成为一个糟糕的 SSLCipherSuite,IIRC。基本上确保您有完整的 SSL 配置:
您定义了密码、证书和密钥吗?SSLEngine 开启了吗?您的配置中至少需要这样的东西......
SSL 引擎开启
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL SSLCertificateFile /path/to/apache/conf/server.crt SSLCertificateKeyFile /path/to/apache /conf/服务器.key
...如果你想验证客户端证书,你还需要类似的东西:
SSLVerifyClient 需要 SSLVerifyDepth 10 SSLCACertificateFile /path/to/apache/conf/trustedpubkeys.crt
祝你好运!
如果您想验证这是否确实发生,请启动 tcpdump 或wireshark 等嗅探器。对于 tcpdump 我会使用像这样的命令行...
tcpdump -i eth0 -nn -s 1600 ip proto 17 和主机 IP_ADDRESS
(其中 IP_ADDRESS 是服务器的 FQDN 或点分四组)
然后获取 $_SERVER var 转储页面或 phpinfo() 页面等。
您的 $_SERVER var 转储显示了您的远程端口,因此您应该能够看到哪些连接使用了该端口,以及它是否连接到端口 80 还是 443。
如果您更喜欢使用 GUI,Wireshark 也会让您做同样的事情。