如何确定是否使用不带$ _SERVER的HTTPS

我在网上看过很多教程,说如果服务器连接是用HTTPS保护的,你需要检查$_SERVER['HTTPS'] 。 我的问题是,在我使用的一些服务器上, $_SERVER['HTTPS']是一个未定义的variables,导致错误。 是否有其他variables,我可以检查,应该总是定义?

只是要清楚,我目前正在使用此代码来解决,如果它是一个HTTPS连接:

 if(isset($_SERVER['HTTPS'])) { if ($_SERVER['HTTPS'] == "on") { $secure_connection = true; } } 

Chacha,根据PHP文档:“如果通过HTTPS协议查询脚本,则设置为非空值。 所以你的if语句在HTTPS确实处于打开状态的许多情况下会返回false。 你需要validation$_SERVER['HTTPS']存在并且是非空的。 在给定服务器的HTTPS设置不正确的情况下,您可以尝试检查$_SERVER['SERVER_PORT'] == 443

但是请注意,有些服务器也会将$_SERVER['HTTPS']设置为非空值,所以一定要检查这个variables。

参考: $_SERVER$HTTP_SERVER_VARS文档[已弃用]

即使未定义$_SERVER['HTTPS']也应该始终工作:

 function isSecure() { return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443; } 

该代码与IIS兼容。

从PHP.net文档和用户注释 :

1)如果通过HTTPS协议查询脚本,则设置为非空值。

2)请注意,在IIS中使用ISAPI时,如果请求不是通过HTTPS协议完成的,则该值将为“off”。 (运行PHP作为Fast-CGI应用程序的IIS7已经报告过相同的行为)。

此外,即使安全连接,Apache 1.x服务器(和损坏的安装)也可能没有定义$_SERVER['HTTPS'] 。 虽然不能保证,但按照惯例 ,端口443上的连接可能使用安全套接字 ,因此需要额外的端口检查。

我的解决scheme(因为标准条件[$ _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:由于反向代理(负载均衡器)可能使用HTTP与Web服务器通信,即使对反向代理的请求是HTTPS http://en.wikipedia,也是用于标识HTTP请求的始发协议的事实标准。组织/维基/ List_of_HTTP_header_fields#Common_non,standard_request_headers

 if( (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || $_SERVER['SERVER_PORT'] == 443 ){ //enable secure connection } 

我刚刚遇到了一个问题,我使用Apache mod_ssl运行服务器,但是phpinfo()和var_dump($ _SERVER)显示PHP仍认为我在端口80上。

这是我的解决方法,任何人都有同样的问题….

 <VirtualHost *:443> SetEnv HTTPS on DocumentRoot /var/www/vhost/scratch/content ServerName scratch.example.com </VirtualHost> 

值得注意的是SetEnv行。 有了这个和重启后,你应该有你一直梦寐以求的HTTPS环境variables

如果你正在使用Apache,你可能总是依靠

 $_SERVER["REQUEST_SCHEME"] 

validation请求的URL的scheme。 但是,正如其他答案中提到的那样,在假定SSL被使用之前validation其他参数是谨慎的。

真正的答案:准备好复制粘贴到一个[configuration]脚本

 / *configuration设置;  X =编辑可能10月11日* /
 $ pv_sslport = 443;  / *因为它可能是不同的,加布里埃尔索萨也表示* /
 $ pv_serverport = 80;  /* X */
 $ pv_servername = “mysite.com”;  /* X */

 / *由迈克尔·考宾斯基修正后附加* /
 if(!isset($ _ SERVER [“SERVER_NAME”])||!$ _ SERVER [“SERVER_NAME”]){
     if(!isset($ _ ENV [“SERVER_NAME”])){
         GETENV( “SERVER_NAME”);
         //设置为env server_name
         $ _SERVER [ “SERVER_NAME”] = $ _ ENV [ “SERVER_NAME”];
     }
 }
如果(!$ _ SERVER [“SERVER_NAME”])(
     / * X服务器名称仍为空?  ...你可以设置$ _SERVER [“SERVER_NAME”] = $ pv_servername;  * /
 }

如果(!isset($ _ SERVER [“SERVER_PORT”])||!$ _ SERVER [“SERVER_PORT”]){
    如果(!isset($ _ ENV [“SERVER_PORT”])){
         GETENV( “SERVER_PORT”);
         $ _SERVER [ “SERVER_PORT”] = $ _ ENV [ “SERVER_PORT”];
     }
 }
如果(!$ _ SERVER [“SERVER_PORT”])(
     / * X服务器端口仍为空?  ...你可能会设置$ _SERVER [“SERVER_PORT”] = $ pv_serverport;  * /
 }

 $ pv_URIprotocol = isset($ _ SERVER [“HTTPS”])?  ($ _SERVER [“HTTPS”] ===“on”|| $ _SERVER [“HTTPS”] === 1 || $ _SERVER [“SERVER_PORT”] === $ pv_sslport)?“https://” :“(($ _SERVER [”SERVER_PORT“] === $ pv_sslport)?”https://“:”http://“);

$pv_URIprotocol现在是正确的,可以使用了; 例如$site=$pv_URIprotocol.$_SERVER["SERVER_NAME"] 。 当然,string也可以用TRUE和FALSE代替。 光伏代表PortalPressvariables,因为它是一个直接的复制粘贴,将始终工作。 这件作品可以在生产脚本中使用。

我不认为添加一个端口是个好主意 – 特别是当你有许多不同版本的服务器时。 这只是增加了一件事情要记住要改变。 看着doc的我认为凯斯的最后一行是相当不错的,所以:

 if(!empty($_SERVER["HTTPS"])) if($_SERVER["HTTPS"]!=="off") return 1; //https else return 0; //http else return 0; //http 

似乎非常完美。

我发现这些参数也可以接受,并且在切换networking服务器时可能没有误报。

  1. $ _ SERVER [ 'HTTPS_KEYSIZE']
  2. $ _ SERVER [ 'HTTPS_SECRETKEYSIZE']
  3. $ _ SERVER [ 'HTTPS_SERVER_ISSUER']
  4. $ _ SERVER [ 'HTTPS_SERVER_SUBJECT']

     if($_SERVER['HTTPS_KEYSIZE'] != NULL){/*do foobar*/} 

您可以检查$_SERVER['SERVER_PORT']因为SSL通常在端口443上运行,但这不是万无一失的。

唯一可靠的方法是由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://"); 

考虑以下几点:你正在使用nginx和fastcgi,默认情况下(debian,ubuntu)fastgi_params包含指令:

fastcgi_param HTTPS $ https;

如果您不使用SSL,则会将其转换为空值,而不是“关”,而不是0,您注定要失败。

http://unpec.blogspot.cz/2013/01/nette-nginx-php-fpm-redirect.html

我正在使用的最短路线:

 $secure_connection = !empty($_SERVER['HTTPS']); 

如果使用https,则$ secure_connection为true。

在我的服务器上(Ubuntu 14.10,Apache 2.4,php 5.5),当php脚本通过https加载时,variables$_SERVER['HTTPS']没有设置。 我不知道什么是错的。 但是下面的.htaccess文件中的行解决了这个问题:

 RewriteEngine on RewriteCond %{HTTPS} =on [NC] RewriteRule .* - [E=HTTPS:on,NE] 

这是我一直在使用的一个可重用的函数。 HTH。

注意:HTTPS_PORT(在我的代码中是一个自定义常量)的值可能会因您的环境而异,例如可能是443或81。

 /** * Determine if this is a secure HTTPS connection * * @return bool True if it is a secure HTTPS connection, otherwise false. */ function isSSL() { if (isset($_SERVER['HTTPS'])) { if ($_SERVER['HTTPS'] == 1) { return true; } elseif ($_SERVER['HTTPS'] == 'on') { return true; } } elseif ($_SERVER['SERVER_PORT'] == HTTPS_PORT) { return true; } return false; } 

你觉得这怎么样?

 if (isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') $scheme = 'https'; else $scheme = 'http'; 

只是为了兴趣,铬金丝雀目前发送

 HTTPS : 1 

到服务器,并根据如何configuration服务器可能意味着你回到以下

 HTTPS : 1, on 

这打破了我们的申请,因为我们正在testing,如果这显然不是。 目前,只有铬金丝雀似乎这样做,但值得注意的是,金丝雀的东西一般在短时间后会在“正常”的铬中着陆。

如果您使用nginx作为负载均衡系统检查$ _SERVER ['HTTP_HTTPS'] == 1,其他检查将失败的ssl。

如果您使用Incapsula的负载均衡器,则需要使用IRule为您的服务器生成自定义标题。 我创build了一个HTTP_X_FORWARDED_PROTO标头,如果端口设置为80则等于“http”,如果等于443,则等于“https”。

 $secure_connection = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || (!empty($_SERVER['HTTP_HTTPS']) && $_SERVER['HTTP_HTTPS'] != 'off') || $_SERVER['REQUEST_SCHEME'] == 'https' || $_SERVER['SERVER_PORT'] == 443) ? true : false; 

代码正在检查任何可能的工作,也在IIS Web服务器上。 自v44以来的Chrome不设置标头HTTP:1,所以检查HTTP_HTTPS是好的。 如果此代码与https不匹配,则意味着您的networking服务器或代理服务器configuration不良。 Apache本身正确设置HTTPS标志,但是当你使用代理(例如nginx)时可能会出现问题。 您必须在nginx https虚拟主机中设置一些标头

 proxy_set_header X-HTTPS 1; 

并通过从代理中寻找X-HTTPS来使用一些Apache模块来正确设置HTTPS标志。 searchmod_fakessl,mod_rpaf等

我会添加一个全局filter,以确保我所检查的一切是正确的;

 function isSSL() { $https = filter_input(INPUT_SERVER, 'HTTPS'); $port = filter_input(INPUT_SERVER, 'SERVER_PORT'); if ($https) { if ($https == 1) { return true; } elseif ($https == 'on') { return true; } } elseif ($port == '443') { return true; } return false; } 

根据hobodave的post:“如果通过HTTPS协议查询脚本,则设置为非空值”。

 if (!empty($_SERVER['HTTPS'])) { $secure_connection = true; }