php 如何确定您是否使用没有 $_SERVER['HTTPS'] 的 HTTPS
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1175096/
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
How to find out if you're using HTTPS without $_SERVER['HTTPS']
提问by Tyler Carter
I've seen many tutorials online that says you need to check $_SERVER['HTTPS']if the server is connection is secured with HTTPS. My problem is that on some of the servers I use, $_SERVER['HTTPS']is an undefined variable that results in an error. Is there another variable I can check that should always be defined?
我在网上看过很多教程,说你需要检查$_SERVER['HTTPS']服务器的连接是否使用 HTTPS 保护。我的问题是,在我使用的某些服务器上,$_SERVER['HTTPS']是一个未定义的变量会导致错误。是否有另一个我可以检查的变量应该总是被定义?
Just to be clear, I am currently using this code to resolve if it is an HTTPS connection:
为了清楚起见,我目前正在使用此代码来解决它是否是 HTTPS 连接:
if(isset($_SERVER['HTTPS'])) {
if ($_SERVER['HTTPS'] == "on") {
$secure_connection = true;
}
}
回答by Gras Double
This should always work even when $_SERVER['HTTPS']is undefined:
即使$_SERVER['HTTPS']未定义,这也应该始终有效 :
function isSecure() {
return
(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
|| $_SERVER['SERVER_PORT'] == 443;
}
The code is compatible with IIS.
该代码与 IIS 兼容。
From the PHP.net documentation and user comments:
1) Set to a non-empty value if the script was queried through the HTTPS protocol.
2) Note that when using ISAPI with IIS, the value will be "off" if the request was not made through the HTTPS protocol. (Same behaviour has been reported for IIS7 running PHP as a Fast-CGI application).
1) 如果脚本是通过 HTTPS 协议查询的,则设置为非空值。
2) 请注意,在 IIS 中使用 ISAPI 时,如果请求不是通过 HTTPS 协议发出的,则该值将是“关闭”。(对于将 PHP 作为 Fast-CGI 应用程序运行的 IIS7,已报告了相同的行为)。
Also, Apache 1.x servers (and broken installations) might not have $_SERVER['HTTPS']defined even if connecting securely. Although not guaranteed, connections on port 443 are, by convention, likely using secure sockets, hence the additional port check.
此外,$_SERVER['HTTPS']即使安全连接,Apache 1.x 服务器(和损坏的安装)也可能没有定义。尽管不能保证,但按照惯例,端口 443 上的连接可能使用安全套接字,因此需要进行额外的端口检查。
Additional note: if there is a load balancer between the client and your server, this code doesn't test the connection between the client and the load balancer, but the connection between the load balancer and your server. To test the former connection, you would have to test using the HTTP_X_FORWARDED_PROTOheader, but it's much more complex to do; see latest commentsbelow this answer.
附加说明:如果客户端和您的服务器之间存在负载均衡器,则此代码不会测试客户端和负载均衡器之间的连接,而是测试负载均衡器和您的服务器之间的连接。要测试前一个连接,您必须使用HTTP_X_FORWARDED_PROTO标头进行测试,但这要复杂得多;请参阅此答案下方的最新评论。
回答by temuraru
My solution (because the standard conditions [$_SERVER['HTTPS'] == 'on'] do not work on servers behind a load balancer) is:
我的解决方案(因为标准条件 [$_SERVER['HTTPS'] == 'on'] 在负载均衡器后面的服务器上不起作用)是:
$isSecure = false;
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
$isSecure = true;
}
elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' || !empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') {
$isSecure = true;
}
$REQUEST_PROTOCOL = $isSecure ? 'https' : 'http';
HTTP_X_FORWARDED_PROTO: a de factostandard for identifying the originating protocol of an HTTP request, since a reverse proxy (load balancer) may communicate with a web server using HTTP even if the request to the reverse proxy is HTTPS http://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Common_non-standard_request_headers
HTTP_X_FORWARDED_PROTO:用于识别 HTTP 请求的原始协议的事实标准,因为即使反向代理的请求是 HTTPS http://en.wikipedia,反向代理(负载均衡器)也可以使用 HTTP 与 Web 服务器通信 。 org/wiki/List_of_HTTP_header_fields#Common_non-standard_request_headers
回答by hobodave
Chacha, per the PHP documentation: "Set to a non-empty value if the script was queried through the HTTPS protocol." So your if statement there will return false in many cases where HTTPS is indeed on. You'll want to verify that $_SERVER['HTTPS']exists and is non-empty. In cases where HTTPS is not set correctly for a given server, you can try checking if $_SERVER['SERVER_PORT'] == 443.
Chacha,根据 PHP 文档:“如果通过 HTTPS 协议查询脚本,则设置为非空值。” 因此,在确实启用 HTTPS 的许多情况下,您的 if 语句将返回 false。您需要验证它$_SERVER['HTTPS']存在且非空。如果给定服务器的 HTTPS 设置不正确,您可以尝试检查$_SERVER['SERVER_PORT'] == 443.
But note that some servers will also set $_SERVER['HTTPS']to a non-empty value, so be sure to check this variable also.
但请注意,某些服务器也会设置$_SERVER['HTTPS']为非空值,因此请务必同时检查此变量。
Reference: Documentation for $_SERVERand $HTTP_SERVER_VARS[deprecated]
回答by Thamaraiselvam
This also works when $_SERVER['HTTPS']is undefined
这在$_SERVER['HTTPS']未定义时也有效
if( (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || $_SERVER['SERVER_PORT'] == 443 ){
//enable secure connection
}
回答by thomas-peter
I have just had an issue where I was running the server using Apache mod_ssl, yet a phpinfo() and a var_dump( $_SERVER ) showed that PHP still thinks I'm on port 80.
我刚刚遇到一个问题,我使用 Apache mod_ssl 运行服务器,但是 phpinfo() 和 var_dump( $_SERVER ) 显示 PHP 仍然认为我在端口 80 上。
Here is my workaround for anyone with the same issue....
这是我对任何有同样问题的人的解决方法......
<VirtualHost *:443>
SetEnv HTTPS on
DocumentRoot /var/www/vhost/scratch/content
ServerName scratch.example.com
</VirtualHost>
The line worth noting is the SetEnv line. With this in place and after a restart, you should have the HTTPS environment variable you always dreamt of
值得注意的行是 SetEnv 行。有了这个并重新启动后,您应该拥有梦寐以求的 HTTPS 环境变量
回答by ling
Making my own function from reading all previous posts:
通过阅读所有以前的帖子制作我自己的功能:
public static function isHttps()
{
if (array_key_exists("HTTPS", $_SERVER) && 'on' === $_SERVER["HTTPS"]) {
return true;
}
if (array_key_exists("SERVER_PORT", $_SERVER) && 443 === (int)$_SERVER["SERVER_PORT"]) {
return true;
}
if (array_key_exists("HTTP_X_FORWARDED_SSL", $_SERVER) && 'on' === $_SERVER["HTTP_X_FORWARDED_SSL"]) {
return true;
}
if (array_key_exists("HTTP_X_FORWARDED_PROTO", $_SERVER) && 'https' === $_SERVER["HTTP_X_FORWARDED_PROTO"]) {
return true;
}
return false;
}
回答by Ed de Almeida
If your are using Apache you may always count on
如果您使用的是 Apache,您可能总是指望
$_SERVER["REQUEST_SCHEME"]
to verify the scheme of the URL requested. But, as mentioned in other answers, it is prudent to verify other parameters before assuming SSL is really being used.
验证请求的 URL 的方案。但是,正如其他答案中所提到的,在假设真正使用 SSL 之前验证其他参数是谨慎的。
回答by Igor M. - PortalPress.org
The REAL answer: ready for copy-paste into a [config] script
真正的答案:准备好复制粘贴到 [config] 脚本中
/* configuration settings; X=edit may 10th '11 */
$pv_sslport=443; /* for it might be different, as also Gabriel Sosa stated */
$pv_serverport=80; /* X */
$pv_servername="mysite.com"; /* X */
/* X appended after correction by Michael Kopinsky */
if(!isset($_SERVER["SERVER_NAME"]) || !$_SERVER["SERVER_NAME"]) {
if(!isset($_ENV["SERVER_NAME"])) {
getenv("SERVER_NAME");
// Set to env server_name
$_SERVER["SERVER_NAME"]=$_ENV["SERVER_NAME"];
}
}
if(!$_SERVER["SERVER_NAME"]) (
/* X server name still empty? ... you might set $_SERVER["SERVER_NAME"]=$pv_servername; */
}
if(!isset($_SERVER["SERVER_PORT"]) || !$_SERVER["SERVER_PORT"]) {
if(!isset($_ENV["SERVER_PORT"])) {
getenv("SERVER_PORT");
$_SERVER["SERVER_PORT"]=$_ENV["SERVER_PORT"];
}
}
if(!$_SERVER["SERVER_PORT"]) (
/* X server port still empty? ... you might set $_SERVER["SERVER_PORT"]=$pv_serverport; */
}
$pv_URIprotocol = isset($_SERVER["HTTPS"]) ? (($_SERVER["HTTPS"]==="on" || $_SERVER["HTTPS"]===1 || $_SERVER["SERVER_PORT"]===$pv_sslport) ? "https://" : "http://") : (($_SERVER["SERVER_PORT"]===$pv_sslport) ? "https://" : "http://");
$pv_URIprotocolis now correct and ready to be used; example $site=$pv_URIprotocol.$_SERVER["SERVER_NAME"]. Naturally, the string could be replaced with TRUE and FALSE also. PV stands for PortalPress Variable as it is a direct copy-paste which will always work. This piece can be used in a production script.
$pv_URIprotocol现在是正确的,可以使用了;例子$site=$pv_URIprotocol.$_SERVER["SERVER_NAME"]。当然,字符串也可以用 TRUE 和 FALSE 替换。PV 代表 PortalPress 变量,因为它是一种始终有效的直接复制粘贴。这件作品可用于制作脚本。
回答by sp3c1
I don't think that adding a port is good idea - specially when you got many servers with different builds. that just adds one more thing to remember to change. looking at doc's I think the last line of kaisers is quite good, so that:
我不认为添加端口是个好主意 - 特别是当你有许多不同版本的服务器时。这只是增加了一件事要记住改变。看着文档,我认为 kaisers 的最后一行非常好,因此:
if(!empty($_SERVER["HTTPS"]))
if($_SERVER["HTTPS"]!=="off")
return 1; //https
else
return 0; //http
else
return 0; //http
seems like perfectly enough.
似乎已经足够了。
回答by Galvani
The only reliable method is the one described by Igor M.
唯一可靠的方法是 Igor M 描述的方法。
$pv_URIprotocol = isset($_SERVER["HTTPS"]) ? (($_SERVER["HTTPS"]==="on" || $_SERVER["HTTPS"]===1 || $_SERVER["SERVER_PORT"]===$pv_sslport) ? "https://" : "http://") : (($_SERVER["SERVER_PORT"]===$pv_sslport) ? "https://" : "http://");
Consider following: You are using nginx with fastcgi, by default(debian, ubuntu) fastgi_params contain directive:
考虑以下事项:您正在使用带有 fastcgi 的 nginx,默认情况下(debian、ubuntu)fastgi_params 包含指令:
fastcgi_param HTTPS $https;
fastcgi_param HTTPS $https;
if you are NOT using SSL, it gets translated as empty value, not 'off', not 0 and you are doomed.
如果您不使用 SSL,它会被转换为空值,而不是“关闭”,而不是 0,并且您注定要失败。
http://unpec.blogspot.cz/2013/01/nette-nginx-php-fpm-redirect.html
http://unpec.blogspot.cz/2013/01/nette-nginx-php-fpm-redirect.html

