背景:网站(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,但如果我可以使用一些正则表达式并以某种方式比较网址,那么会更好(更省力)。
我还想知道可能的问题和漏洞。
谢谢:)
答案 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';
}