48

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

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

<?php

header('Content-Type: text/plain');

print_r($_SERVER);

输出:

[REQUEST_SCHEME] => http

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

我在windows下使用VC9 PHP 5.4.14 TS开发。但是我的制作是在ubuntu下的。Q#2:这个属性在 ubuntu linux 下也可用吗?

4

9 回答 9

59

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 环境。对于分布式代码,这可能不是一个好的解决方案,但它可以很好地满足我的需求。

于 2014-04-20T02:14:38.110 回答
36

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

于 2013-08-02T03:20:03.100 回答
24

由于此变量并非在所有 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 自 2.4 版以来就是 Apache Web 服务器的本机变量。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 中的最佳实践 - 请参阅thisthat)。

于 2016-11-23T19:02:45.623 回答
10

我也找不到对 的引用REQUEST_SCHEME,但是如果您要确定请求是否由http:https:然后您可以使用$_SERVER['HTTPS'],如果请求由https:. 它记录在 PHP 站点here

于 2013-08-02T03:16:50.463 回答
5

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

于 2015-06-03T11:39:22.133 回答
4

该值取决于您的网络服务器。如果您使用 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's answer

于 2017-09-05T09:49:19.170 回答
3

有趣的是,WordPress 如何通过使用 $_SERVER 变量的is_ssl()函数解决这个问题,

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;
}
于 2019-04-23T11:37:18.480 回答
2

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

    /**
     * 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';
于 2019-08-03T11:06:27.943 回答
2

加强 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]
于 2017-01-25T15:40:07.497 回答