$_SERVER['REQUEST_SCHEME'] 可靠吗?



我最近正在寻找一种方法来正确确定协议,根据该协议向服务器提供 url 请求。

我观察了parse_url(),虽然$_SERVER超全局变量,发现了这个:

<?php
header('Content-Type: text/plain');
print_r($_SERVER);

输出:

[REQUEST_SCHEME] => http

但是,我无法在 php.net 或谷歌上找到它。不过,我能够找到这个问题问#1:如果没有记录$_SERVER['REQUEST_SCHEME'],那么它可能不可靠,或者它可以信任?

我正在使用 Windows 下的VC9 PHP 5.4.14 TS进行开发。但我的生产是在 ubuntu 下进行的。问#2:此属性在 ubuntu Linux 下也可用吗?

REQUEST_SCHEME 环境变量记录在 Apache mod_rewrite 页面上。但是,直到Apache 2.4才可用。

我只有Apache 2.2,所以我创建了一个环境变量。我在 .htaccess 文件的顶部添加了以下内容。

RewriteEngine on
# Set REQUEST_SCHEME (standard environment variable in Apache 2.4)
RewriteCond %{HTTPS} off
RewriteRule .* - [E=REQUEST_SCHEME:http]
RewriteCond %{HTTPS} on
RewriteRule .* - [E=REQUEST_SCHEME:https]

现在我可以使用

  • %{ENV:REQUEST_SCHEME}其他重写条件和规则
  • $_SERVER['REQUEST_SCHEME']在我的 PHP 代码中

我不必到处做额外的混乱条件检查,而且我的PHP代码是向前兼容的。当Apache升级时,我可以更改我的.htaccess文件。

我不知道你如何把它应用到Windows环境中。对于分布式代码来说,这可能不是一个很好的解决方案,但它非常适合我的需求。

很难证明它是可靠的,但很容易证明它不可靠(如果我能提供一个它不起作用的情况(。我可以证明它是不可靠的,因为它不适用于IIS 7.0 + PHP 5.3

由于此变量并非在所有 Web 服务器版本中都可用,因此仅对其进行测试并不可靠。相反,您可以更改 PHP 代码以测试另外两个服务器环境变量,这也可以指示正在使用 https,如下所示:

if ( (! empty($_SERVER['REQUEST_SCHEME']) && $_SERVER['REQUEST_SCHEME'] == 'https') ||
     (! empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ||
     (! empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == '443') ) {
    $server_request_scheme = 'https';
} else {
    $server_request_scheme = 'http';
}

正如toxalot所说,REQUEST_SCHEME是ApacheWeb服务器自2.4版本以来的本机变量。Apache 2.2 没有它(请参阅 Apache 2.2 服务器变量(,Microsoft IIs 8.5 也没有它(请参阅 IIS 8.5 服务器变量(。当然,如果服务器没有设置变量,PHP 将不会将其包含在其全局数组 $_SERVER 中。

幸运的是,为了与专门基于REQUEST_SCHEME检查的代码兼容,您可以在 Apache 2.2 中创建此变量,编辑所有主机配置文件(httpd.conf、ssl.conf、000-default.conf、vhosts.conf(,添加以下行:

# FOR HOSTS LISTENING AT PORT 80
SetEnvIf Request_Protocol ^HTTP/ REQUEST_SCHEME=http
# FOR HOSTS LISTENING AT PORT 443
SetEnvIf Request_Protocol ^HTTP/ REQUEST_SCHEME=https

上面的代码假定每个协议都使用一个虚拟主机(Apache 中的最佳实践 - 请参阅此处和该内容(。

我也找不到对REQUEST_SCHEME的引用,但是如果您想确定请求是由http:还是https:发出的,那么您可以使用$_SERVER['HTTPS'],如果请求是由https:发出的,则设置为非空值。它记录在PHP网站上

这里

在新版 Nginx 中,默认设置fastcgi_param REQUEST_SCHEME $scheme .

此值取决于您的 Web 服务器。如果您使用 nginx (v1.10(,在文件/etc/nginx/fastcgi_params中您可以看到以下行:

fastcgi_param  REQUEST_SCHEME     $scheme; 
fastcgi_param  HTTPS              $https if_not_empty;

通常,此默认值就足够了。但是它可能不起作用,您可以在vhost中强制使用此值:

include fastcgi_params;
fastcgi_param  REQUEST_SCHEME     https; 
fastcgi_param  HTTPS              On;

如果你使用Apache,你可以看看toxalot的答案

有趣的是,

WordPress如何使用其is_ssl((函数解决这个问题,该函数利用$_SERVER变量,

function is_ssl() {
    if ( isset( $_SERVER['HTTPS'] ) ) {
        if ( 'on' == strtolower( $_SERVER['HTTPS'] ) ) {
            return true;
        }
        if ( '1' == $_SERVER['HTTPS'] ) {
            return true;
        }
    } elseif ( isset( $_SERVER['SERVER_PORT'] ) && ( '443' == $_SERVER['SERVER_PORT'] ) ) {
        return true;
    }
    return false;
}

我正在使用这个,我认为这是获取当前方案的最佳方式

    /**
     * Is Secure?
     * Determines if the application is accessed via an encrypted
     * (HTTPS) connection.
     *
     * @return  bool
     */
    public static function isSecure()
    {
        if (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') {
            return true;
        } elseif (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https') {
            return true;
        } elseif (!empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) !== 'off') {
            return true;
        } elseif (isset($_SERVER['SERVER_PORT']) && intval($_SERVER['SERVER_PORT']) === 443) {
            return true;
        }
        return false;
    }

定义此函数并检查服务器 ssl 连接以获取当前方案

        $scheme = isSecure() ? 'https' : 'http';

增强 toxalot 对 CloudFlare 用户的建议:

RewriteEngine on
RewriteCond %{HTTPS} !on [OR]
RewriteCond %{HTTP:CF-Visitor} '"scheme":"http"'
RewriteRule .* - [E=REQUEST_SCHEME:http]
RewriteCond %{HTTPS} on [OR]
RewriteCond %{HTTP:CF-Visitor} '"scheme":"https"'
RewriteRule .* - [E=REQUEST_SCHEME:https]

相关内容

  • 没有找到相关文章

最新更新