如何确定是否使用不带$ _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服务器时可能没有误报。
- $ _ SERVER [ 'HTTPS_KEYSIZE']
- $ _ SERVER [ 'HTTPS_SECRETKEYSIZE']
- $ _ SERVER [ 'HTTPS_SERVER_ISSUER']
-
$ _ 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; }