$_SERVER 返回的端口号不正确['server_port']

2022-08-30 23:30:57

场景:我正在使用一些PHP在Apache Web服务器上工作。我将浏览器指向包含以下代码行的 https://my.example.com/test.php

<pre>
<?php
print_r($_SERVER);
?>
</pre>

SERVER_PORT打印出来的值为 80,而不是 443。但是,如果我去 https://my.example.com:80/test.php Web服务器(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地址替换为单词IP_ADDRESS):

Listen IP_ADDRESS:443    
<VirtualHost *:443>
        ServerName my.example.com
        ServerAlias my
        DocumentRoot "/path/to/document_root/htdocs"
        Options +Indexes
</VirtualHost>

以下是 $_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
)

如您所见,SERVER_PORT为80,未设置$ _SERVER['HTTPS']。根据PHP文档,我认为如果通过HTTPS访问PHP脚本,它应该设置为非空值(这就是我正在做的事情)。

知道发生了什么吗?我只是Web开发人员 - 我不管理这个服务器,但我的服务器管理员告诉我一切都在工作,但我想知道为什么$ _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:将SSL指令移动到VirtualHost指令中,并将该指令更改为使用其IP地址而不是通配符来引用我的站点似乎已经解决了这个问题)。


答案 1

我最近遇到了同样的问题,因为我的一些代码掩盖了同样的问题。

我对这个问题的诊断如下:这是Apache 2.0中所做的更改的一个怪癖。Port 指令不再是 httpd.conf 指令的一部分,实质上是在 ServerName 和 Listen 指令之间拆分的。

所以我的apache httpd.conf(Apache 2.2.23)有这些条目

ServerName myservername.com
Listen: 5150

然而,PHP $_SERVER ['SERVER_PORT'] 向端口 5150 上发出的所有请求返回 80。

因此,仔细研究Apache文档,我发现了一个关于Port是弃用指令和ServerName包含它的花絮。

我设置我的服务器名称指令,如下所示

ServerName myservername.com:5150
UseCanonicalName On
Listen 5150

突然之间,php脚本做了正确的事情,将_SERVER['SERVER_PORT']报告为5150。

或者,您的 httpd.conf 可以读取

ServerName myservername.com
UseCanonicalName Off
Listen 5150

因此,我深入研究了php(5.3.20)源代码和apache源代码,直到我找到行为的来源。

该行为植根于(至少对于 apached 2.2.23 源代码)中的查看函数dirOfApacheSource/server/core.cAP_DECLARE(apr_port_t) ap_get_server_port(const request_rec *r)

在这里,您将看到,如果您的 httpd UseCanonicalName 指令设置为“On”,则 port 将从 ServerName 指令中解析出来。当 ServerName 指令的格式不是 ServerName myserver.com:myport 编号时,案例代码将获取请求对象的ap_default_port(apache 人员将其设置为默认值为 80)。

如果需要将端口显式添加到 httpd.conf 中的 ServerName 指令,则另一个选择是将 UseCanonicalName 设置为“Off”,这将强制 server/core.c 中的代码解析 URI 请求以提取服务器名称和端口。

一个中的六个,另一个中的六个,调整你的apache httpd.conf文件,你很快就会看到预期的结果。


答案 2

好吧,我想我弄清楚了。我的服务器管理员将 conf.d/ssl.conf

SSLEngine On
# and other SSL directives

<VirtualHost *:443>
        ServerName my.example.com
        ServerAlias my

        # and more directives
</VirtualHost>

<VirtualHost IP_ADDRESS:443>
        ServerName my.example.com
        ServerAlias my

        SSLEngine On
        # and other SSL directives

        # and more directives
</VirtualHost>

现在PHP看到了正确的SERVER_PORT#(443),并且现在还设置了$_SERVER['HTTPS']。因此,它要么将SSL指令放在VirtualHost指令中以用于 my.example.com 要么将VirtualHost指令更改为引用实际的IP地址,而不是解决此问题的通配符。感谢大家在这方面的帮助。


推荐