PHP https检查灵活的ssl(cloudflare),该怎么办?

时间:2014-05-08 04:56:28

标签: php ssl https cloudflare

背景:网站(example.com),dns通过cloudflare pro计划设置,这提供了"灵活的ssl" (read here),这意味着ssl仅存在于客户端和cloudflare之间,而不存在于cloudflare和服务器之间,因此不需要专用IP而不需要在服务器上进行特殊设置。服务器设置为不使用ssl(只是一个通用网站),但是cloudflare灵活的ssl正在处理ssl方面。

语言:PHP(codeignighter,但这并不重要)

目标:浏览域名时#34; exmple.com/ "或" http:// exmple.com/" ;,生成变量" http:// example.com",并在浏览到" https时:// example.com/*"生成变量" https:// example.com"。

应该做什么(但不是):

$root = '';
if( isset($_SERVER['HTTPS'] )  && $_SERVER['HTTPS'] != 'off' )
{
    //it doesnt reach here...
    $root .= 'https://';
}
else
{
    $root .= 'http://';
}
$root  .= "".$_SERVER['HTTP_HOST'];
$root .= str_replace(basename($_SERVER['SCRIPT_NAME']),"",$_SERVER['SCRIPT_NAME']);

我总是可以做到:" // example.com",但这对我来说并没有真正解决问题。 思考?我应该做一些字符串比较来确定https-ness?

我确定原因是当请求到达服务器(https或http)时,它来自端口80并且它不会被识别为ssl,因此$ _SERVER [' HTTPS']不是定义。我可以在服务器和cloudflare之间设置一个自定义的ssl,但如果我可以使用一些正则表达式并以某种方式比较网址,那么会更好(更省力)。

我还想知道可能的问题和漏洞。

谢谢:)

5 个答案:

答案 0 :(得分:28)

好的,我将回答有关同一问题的未来人的问题:

if(!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])){
    $root .= $_SERVER['HTTP_X_FORWARDED_PROTO'].'://';
}
else{
    $root .= !empty($_SERVER['HTTPS']) ? "https://" : "http://";
}

当我仔细查看$_SERVER并搜索HTTP_X_FORWARDED_PROTO并找到几页证实这一点时,我就碰到了它。

答案 1 :(得分:8)

$_SERVER['HTTP_X_FORWARDED_PROTO']对我不起作用。我不知道为什么。无论如何,这是我的解决方案:

function is_https_buttflare() {
    return isset($_SERVER['HTTPS']) ||
        ($visitor = json_decode($_SERVER['HTTP_CF_VISITOR'])) &&
            $visitor->scheme == 'https';
}

答案 2 :(得分:0)

我遇到了同样的问题,我在执行var_dump($ _ SERVER)时无法显示$ _SERVER [“HTTPS”]变量。在CloudFlare中,有三种SSL设置(灵活SSL,完整SSL和完整SSL(严格)。对于具有的服务器 自签名证书,建议使用完整SSL。在我将设置更改为完整SSL后,$ _SERVER [“HTTPS”]变量出现,$ _SERVER [“SERVER_PORT”]从80更改为443.现在我可以验证我的页面是否为HTTPS或更不容易,如这样:

terms

在发现这些更改之前,我依赖$ _SERVER [“HTTP_CF_VISITOR”]并验证方案,通过公共IP地址访问页面时一切正常,但在本地访问页面时,换句话说,“ localhost“作为URL,$ _SERVER [”HTTP_CF_VISITOR“]不存在,但$ _SERVER [”HTTPS“]确实......所以我的问题是,通过公共IP地址访问页面,$ _SERVER [”HTTPS“]没有显示和$ _SERVER [“HTTP_CF_VISITOR”]。反之亦然。

答案 3 :(得分:0)

我这样做是为了检查所有结果:

        // check if ssl used on server
        if ( (!empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' ) || $_SERVER['SERVER_PORT'] == 443 ){

            echo '<script>console.log("https")</script>';

        //check if ssl used on load balancers such as cloudflare
        }elseif ( !empty( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' ) {

            echo '<script>console.log("https")</script>';

        }else{

            echo '<script>console.log("http")</script>';

        }

答案 4 :(得分:-1)

您是否尝试过检查$ _SERVER [&#39; SERVER_PORT&#39;]变量?这应该回归&#39; 80&#39;如果它只是一个HTTP连接,或者&#39; 443&#39;如果你正在使用HTTPS连接。

所以这样的函数应该有效:

function get_http()
{
    if ($_SERVER['SERVER_PORT'] == '443')
    {
        return 'https';
    }

    return 'http';
}