2013-08-02 207 views
28

我最近正在寻求一种方法来正确确定协议,在哪个url请求被提供给服务器。

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

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

print_r($_SERVER); 
?> 

输出:

[REQUEST_SCHEME] => HTTP

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

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

回答

29

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

+7

+1的最安全方式,回答。 –

+0

谢谢。我用'PHP 5.4.17'生产也没有显示它。 – BlitZ

+0

Windows上的Zend Server CE不兼容! – Benjamin

6

我也无法找到REQUEST_SCHEME一个参考,但如果你正在寻找确定请求是否被http:https:做出那么你可以使用$_SERVER['HTTPS'],它被设置为一个非空值,如果https:发出了请求。它记录在PHP网站上here

+5

在一定条件下'$ _ SERVER [” HTTPS']给出非空值('off'),表明HTTPS未被使用。关于答案中链接的页面的更多信息。 –

+0

@ F-3000感谢您的留言。这非常有用。 – BlitZ

+11

'''isset($ _ SERVER ['HTTPS'])&&'on'=== $ _SERVER ['HTTPS']'''似乎是确定https:// –

43

REQUEST_SCHEME环境变量在Apache mod_rewrite page记录。但是,它直到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环境。这对于分布式代码来说可能不是一个好的解决方案,但它可以满足我的需求。

+0

不过,谢谢。很高兴知道它来自哪里。 – BlitZ

5

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

3

由于此变量不适用于所有服务器版本,所以当然不可靠,只能测试它。 相反,你可以改变你的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是因为版本的Apache的本地变量2.4(Apache 2.2没有它)。而且,如果该变量未被服务器设置,PHP将不会将其包含在其全局数组$ _SERVER中。

幸运的是,与REQUEST_SCHEME检查exclusevily基于代码的兼容性,您可以创建在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 
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] 
+0

我应该补充说,这个头文件是JSON,技术上他们可以在冒号后面添加空格并打破该配置的逻辑,但我明白Apache不允许解析JSON,Cloudflare的工作人员可能知道人们正在执行字符串在JSON内匹配..有关Cloudflare特殊标题的详细信息:https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-CloudFlare-handle-HTTP-Request-headers- –

1

此值取决于你的Web服务器上。如果您使用的nginx(V1.10),在文件/etc/nginx/fastcgi_params你可以看到这下面几行:

fastcgi_param REQUEST_SCHEME  $scheme; 
fastcgi_param HTTPS    $https if_not_empty; 

一般情况下,这个默认值即可。 但它是可能的,它不工作,你可以强制在你的虚拟主机这个值:

include fastcgi_params; 
fastcgi_param REQUEST_SCHEME  https; 
fastcgi_param HTTPS    On; 

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