有没有办法检查当前页面是否使用SSL打开?例如,我希望我的登录页面(login.php)检查是否使用SSL(https://mywebserver.com/login.php)访问它。如果没有,请将它们重定向到页面的SSL版本。
实际上,我想让用户安全地使用该页面。
答案 0 :(得分:54)
您应该能够检查是否设置了$_SERVER['HTTPS']
,例如:
if (empty($_SERVER['HTTPS'])) {
header('Location: https://mywebserver.com/login.php');
exit;
}
答案 1 :(得分:32)
小心点。在我的IIS服务器上,$ _SERVER ['HTTPS']不为空,但值为'off'。
所以我必须这样做
if (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != 'on') {
// no SSL request
}
答案 2 :(得分:9)
如果您正在处理转发的协议,您会发现这可能不起作用。例如,亚马逊的ELB可以处理SSL协商并通过端口80与您的应用服务器进行交互。
此块处理:
public function isSSL()
{
if( !empty( $_SERVER['https'] ) )
return true;
if( !empty( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' )
return true;
return false;
}
答案 3 :(得分:4)
<?php
if ( !empty( $_SERVER['HTTPS'] ) ) {
//do secure stuff
}else{
//warn or redirect or whatever
}
?>
答案 4 :(得分:4)
嗯,这是另一块代码。代码将使用https / http。
返回完整的URL<?php
/**
* Check whether URL is HTTPS/HTTP
* @return boolean [description]
*/
function isSecure()
{
if (
( ! empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
|| ( ! empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
|| ( ! empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on')
|| (isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443)
|| (isset($_SERVER['HTTP_X_FORWARDED_PORT']) && $_SERVER['HTTP_X_FORWARDED_PORT'] == 443)
|| (isset($_SERVER['REQUEST_SCHEME']) && $_SERVER['REQUEST_SCHEME'] == 'https')
) {
return true;
} else {
return false;
}
}
/**
* Example Use
*/
define('APP_URL', (isSecure() ? 'https' : 'http') . "://{$_SERVER['SERVER_NAME']}".str_replace(basename($_SERVER['SCRIPT_NAME']),"",$_SERVER['SCRIPT_NAME']));
echo APP_URL;
/**
* +++++++++++++++++++++++++
* OR - One line Code
* +++++++++++++++++++++++++
*/
define('APP_URL', ((( ! empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || ( ! empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') || ( ! empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') || (isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443) || (isset($_SERVER['HTTP_X_FORWARDED_PORT']) && $_SERVER['HTTP_X_FORWARDED_PORT'] == 443) || (isset($_SERVER['REQUEST_SCHEME']) && $_SERVER['REQUEST_SCHEME'] == 'https') ) ? 'https' : 'http') . "://{$_SERVER['SERVER_NAME']}".str_replace(basename($_SERVER['SCRIPT_NAME']),"",$_SERVER['SCRIPT_NAME']));
echo APP_URL;
?>
答案 5 :(得分:2)
只是在nginx的情况下添加,检查https的方法是:
if (isset($_SERVER['SERVER_PORT']) &&
($_SERVER['SERVER_PORT'] === '443')) {
return 'https';
}
答案 6 :(得分:2)
另一种方法是检查是否存在HTTPS cookie。首先,您的服务器需要向浏览器发送带有secure
标志的cookie:
Set-Cookie:some_key=some_value;secure
在您的服务器向浏览器发送Cookie后,只要浏览器从您的服务器请求某个页面,只有在请求HTTPS页面时,它才会发送安全Cookie some_key=some_value
。这意味着如果您看到cookie some_key=some_value
的存在,您就知道浏览器正在请求HTTPS页面。瞧!
浏览器支持非常好,因为这是安全性的基础。当用户从非HSTSed域请求页面时,不支持HTTPS cookie的浏览器为Firesheepable。
有关详细信息,请参阅:
答案 7 :(得分:0)
要使用PHP检查是否在没有SSL的情况下访问了页面,您可以检查端口号。
// Most encrypted web sites use port 443
if ($_SERVER['SERVER_PORT']==443) {
// Tell browser to always use HTTPS
header('strict-transport-security: max-age=126230400');
}
elseif (isset($_SERVER['SERVER_PORT'])) {
// Redirect current page to https with 301 Moved Permanently response
header('location: https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'], true, 301);
exit;
}
这假定您的服务器配置了SERVER_PORT环境变量,并且网站的加密版本托管在端口443上。它还假定您的服务器不在负载均衡器的后面。如果您的服务器位于负载均衡器的后面,则您可能需要一种更高级的解决方案,例如这种不依赖于自定义HTTP标头的解决方案,该HTTP标头可能会因一个负载均衡器而异于另一个负载均衡器:
// Set secure cookie to detect HTTPS as cookie will not exist otherwise.
header('set-cookie: __Secure-https=1; expires='.substr(gmdate('r', ($_SERVER['REQUEST_TIME']?: time())+126230400), 0, -5).'GMT; path=/; secure', false);
// Tell browser to always use HTTPS
header('strict-transport-security: max-age=126230400');
if (!isset($_COOKIE['__Secure-https']) && !isset($_GET['https'])) {
// Redirect to secure version of site and add https=1 GET variable in case cookies are blocked
header('location: https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].(strpos($_SERVER['REQUEST_URI'], '?')===false? '?': '&').'https=1', true, 307);
exit;
}
如果上述解决方案由于在URL上添加?https = 1而有问题,那么您可以随时使用JavaScript。在
之后将其添加到页面顶部:<script>
// This will redirect all requests from http to https
if (location.protocol=='http:') {
location.replace('https://'+location.host+location.pathname+location.search)
document.write('<noscript>');// hack to stop page from displaying
}
</script>
然后,如果您希望浏览器记住访问站点时始终使用HTTPS,请在PHP脚本中添加以下内容:
header('strict-transport-security: max-age=126230400');
或者如果您希望浏览器预先加载您的首选项,请使用:
header('strict-transport-security: max-age=126230400; preload');// HTTPS will always be used!
如果使用预加载功能,则需要提交要包含在Chrome的HSTS预加载列表中的网站,以便浏览器可以预加载您的网站偏好设置。如果您使用预加载,建议您在不带www的裸域上托管您的网站。这是因为对于大多数人来说,通常不需要www即可更轻松地键入您的域,并且可以通过预加载来轻松加载网站,而无需进行繁琐的重定向,因为https已经是默认设置。
答案 8 :(得分:0)
检测服务器端 SLL 并添加一些内容:
function detectSSL(): ?bool {
// check HTTPS protocol
if( isset($_SERVER['HTTPS']) ) {
if( 'off' !== strtolower($_SERVER['HTTPS']) ) {
return true;
}
if( 1 === (int)$_SERVER['HTTPS'] ) {
return true;
}
}
if( isset($_SERVER['HTTP_X_FORWARDED_SSL']) ) {
if( 'on' === $_SERVER['HTTP_X_FORWARDED_SSL'] ) {
return true;
}
}
if( isset($_SERVER['HTTP_X_FORWARDED_PORT']) ) {
if( 443 === (int)$_SERVER['HTTP_X_FORWARDED_PORT'] ) {
return true;
}
}
if( isset($_SERVER['HTTP_X_FORWARDED_PROTO']) ) {
if( strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https' ) {
return true;
}
}
if( isset($_SERVER['REQUEST_SCHEME']) ) {
if( strtolower($_SERVER['REQUEST_SCHEME'] === 'https') ) {
return true;
}
}
// check server port
if( isset($_SERVER['SERVER_PORT']) ) {
if( 443 === (int)$_SERVER['SERVER_PORT'] ) {
return true;
}
}
// non-SSL
return null;
}
// Set URI prefix
define('uri_prefix', detectSSL() ? 'https://' : 'http://');
define('site_host', strtolower(uri_prefix . $_SERVER['HTTP_HOST']));
和 .htaccess 的补充:
# SSL schema off
RewriteCond %{HTTPS} off
RewriteRule .* - [E=REQUEST_SCHEME:http]
# SSL schema
RewriteCond %{HTTPS} on
RewriteRule .* - [E=REQUEST_SCHEME:https]