php $_SERVER['REQUEST_SCHEME'] 可靠吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18008135/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 16:47:19  来源:igfitidea点击:

Is $_SERVER['REQUEST_SCHEME'] reliable?

phpurl-parsing

提问by BlitZ

I recently was seeking a way to properly determine protocol, under which url request was supplied to the server.

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

I watched through parse_url()and though $_SERVERsuperglobal variable, and found this:

我看着通过parse_url(),虽然$_SERVER超全局变量,发现这一点:

<?php

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

print_r($_SERVER);

Output:

输出:

[REQUEST_SCHEME] => http

[REQUEST_SCHEME] => http

However, I was unable to find it on php.netor Google. Though, I was able to find thisquestion. Q#1:If $_SERVER['REQUEST_SCHEME']wasn't documented, then it is probably unreliable, or it can be trusted?

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

I'am using VC9 PHP 5.4.14 TSunder windows for development. But my production is under ubuntu. Q#2:Is this property also availible under ubuntu linux too?

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

采纳答案by invisal

It is hard to prove that it is reliable, but it is easy to prove that it is not reliable (if only I could provide a case which it does not work). And I can prove that it is unreliable because it does not work with IIS 7.0 + PHP 5.3

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

回答by toxalot

The REQUEST_SCHEMEenvironment variable is documented on the Apache mod_rewrite page. However, it didn't become available until Apache 2.4.

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

I only have Apache 2.2 so I created an environment variable. I added the following to the top of my .htaccess file.

我只有 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]

Now I can use

现在我可以使用

  • %{ENV:REQUEST_SCHEME}in other rewrite conditions and rules
  • $_SERVER['REQUEST_SCHEME']in my PHP code
  • %{ENV:REQUEST_SCHEME}在其他重写条件和规则中
  • $_SERVER['REQUEST_SCHEME']在我的 PHP 代码中

I don't have to do extra messy conditional checks everywhere, and my PHP code is forward compatible. When Apache is upgraded, I can change my .htaccess file.

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

I don't know how you'd apply this to a Windows environment. This is probably not a good solution for distributed code, but it works well for my needs.

我不知道您如何将其应用于 Windows 环境。对于分布式代码来说,这可能不是一个好的解决方案,但它可以很好地满足我的需求。

回答by aldemarcalazans

As this variable is not available in all web server versions, it is not reliable testing only it. Instead, you can change your PHP code to test two more server environment variables, which can also indicate that https is being used, as below:

由于此变量并非在所有 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';
}

As remarked by toxalot, REQUEST_SCHEME is a native variable of Apache web server since its version 2.4. Apache 2.2 does not have it (see Apache 2.2 server variables)and Microsoft IIs 8.5 does not have it either (see IIS 8.5 Server Variables). Naturally, if a variable is not set by the server, PHP will not include it in its global array $_SERVER.

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

Fortunately, for compatibility with codes based exclusively on REQUEST_SCHEME checking, you can create this variable in Apache 2.2 editing allyour host configuration files (httpd.conf, ssl.conf, 000-default.conf, vhosts.conf), adding the following lines:

幸运的是,为了与完全基于 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

The code above presume the use of one vhost for every protocol (a best practice in Apache - see thisand that).

上面的代码假定每个协议都使用一个 vhost(Apache 中的最佳实践 - 请参阅thisthat)。

回答by aldemarcalazans

I, too, couldn't find a reference to REQUEST_SCHEME, but if you're looking to determine whether a request was made by http:or https:then you can use $_SERVER['HTTPS'], which is set to a non-empty value if a request was made by https:. It's documented on the PHP site here

我也一样,找不到一个参考REQUEST_SCHEME,但如果你正在寻找确定请求是否被提出http:或者https:那么你可以使用$_SERVER['HTTPS'],它被设置为一个非空值,如果一个请求被提出https:。它记录在PHP站点这里

回答by S.A.N

In new version Nginx, set by default fastcgi_param REQUEST_SCHEME $scheme.

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

回答by Arno

This value depends on your web-server. If you use nginx (v1.10), in file /etc/nginx/fastcgi_paramsyou can see this following lines :

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

fastcgi_param  REQUEST_SCHEME     $scheme; 
fastcgi_param  HTTPS              $https if_not_empty;

Generally, this default values are sufficient. But it is possible that it does not work, you can force this values in your vhost :

一般来说,这个默认值就足够了。但它可能不起作用,您可以在 vhost 中强制使用此值:

include fastcgi_params;
fastcgi_param  REQUEST_SCHEME     https; 
fastcgi_param  HTTPS              On;

If you use Apache, you can take a look toxalot's answer

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

回答by Aurovrata

Its interesting to see how WordPress resolves this issue with its is_ssl()function which makes use of $_SERVER variable,

有趣的是,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;
}

回答by Sinus Mackowaty

Enhancing toxalot's suggestion for CloudFlare users:

增强 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]

回答by Mr.Hosseini

I'm using this and i think it's best way to get the current scheme

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

    /**
     * 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;
    }

Define this function and check server ssl connection to get current scheme

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

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