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

只是为了清楚一点,我目前正在使用这段代码来解决它是否是一个HTTPS连接:

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

当前回答

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

其他回答

这应该总是工作,即使$_SERVER['HTTPS']是未定义的:

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

该代码与IIS兼容。

根据PHP.net文档和用户评论:

如果通过HTTPS协议查询脚本,请设置为非空值。 注意,当ISAPI与IIS一起使用时,如果请求不是通过HTTPS协议发出的,则该值将为“off”。(同样的行为也被报道为IIS7将PHP作为Fast-CGI应用程序运行)。

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

另外注意:如果在客户端和服务器之间有一个负载均衡器,这段代码不会测试客户端和负载均衡器之间的连接,而是测试负载均衡器和服务器之间的连接。要测试前一个连接,你必须使用HTTP_X_FORWARDED_PROTO头进行测试,但这要复杂得多;请看这个答案下面的最新评论。

如果你正在使用Apache,你可以一直依赖它

$_SERVER["REQUEST_SCHEME"]

验证所请求URL的方案。但是,正如在其他回答中提到的,在假设真的使用SSL之前,验证其他参数是谨慎的。

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

我使用的最短方法:

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

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

我有机会进一步确定我要连接的网站是否具有SSL能力(一个项目要求用户提供他们的URL,我们需要验证他们已经在http或https网站上安装了我们的API包)。

这是我使用的函数-基本上,只是通过cURL调用URL,看看https是否有效!

function hasSSL($url) 
{
    // take the URL down to the domain name
    $domain = parse_url($url, PHP_URL_HOST);
    $ch = curl_init('https://' . $domain);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'HEAD'); //its a  HEAD
    curl_setopt($ch, CURLOPT_NOBODY, true);          // no body
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);  // in case of redirects
    curl_setopt($ch, CURLOPT_VERBOSE, 0); //turn on if debugging
    curl_setopt($ch, CURLOPT_HEADER, 1);     //head only wanted
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);    // we dont want to wait forever
    curl_exec($ch);
    $header = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    if ($header === 200) {
        return true;
    }
    return false;
}

这是我发现的最可靠的方法,不仅可以知道你是否正在使用https(正如问题所问的那样),而且可以知道你是否可以(甚至应该)使用https。

注意:有可能(虽然不太可能…)一个网站可以有不同的http和https页面(所以如果你被告知使用http,也许你不需要改变..)绝大多数网站都是一样的,可能需要重新路由你自己,但这个额外的检查是有用处的(当然,就像我说的,在用户输入他们的网站信息的项目中,你想从服务器端确保)