php检查请求是否为https

检查请求是否为https,一般可以通过$_SEVER变量中HTTPS和端口是否是443判断:

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

前面工作中遇到微信分享失败(没有缩略图的样式),检查原因是签名失败。通过日志发现签名计算的url地址是http开头的,并非https,但我访问的地址是https。将$_SERVER加入日志中查看,

发现$_SERVER中没有HTTPS变量,SERVER_PORT也是80端口,但看到了另外两个值为https的变量:HTTP_X_FORWARDED_PROTOHTTP_X_CLIENT_PROTO。在搜索引擎中检索HTTP_X_FORWARDED_PROTO, 可以在MDN中看到X_FORWARDED_PROTO的解释:

The X-Forwarded-Proto (XFP) header is a de-facto standard header for identifying the protocol (HTTP or HTTPS) that a client used to connect to your proxy or load balancer. Your server access logs contain the protocol used between the server and the load balancer, but not the protocol used between the client and the load balancer. To determine the protocol used between the client and the load balancer, the X-Forwarded-Proto request header can be used.

就是说当网站有使用代理或者负载均衡时,这时服务器判断是否是https,需要通过HTTP_X_FORWARDED_PROTO判断,因为代理或者负载均衡和服务器之间可能通过http通信的。所以上面的方法应
改为:

function is_ssl(){
    return isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 1 || strtolower($_SERVER['HTTPS']) === 'on') 
        || isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443
        || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https'
        || isset($_SERVER['HTTP_X_CLIENT_PROTO']) && $_SERVER['HTTP_X_CLIENT_PROTO'] === 'https';
}