使用PHP检查是否使用SSL访问了页面

时间:2011-02-24 03:55:57

标签: php ssl

有没有办法检查当前页面是否使用SSL打开?例如,我希望我的登录页面(login.php)检查是否使用SSL(https://mywebserver.com/login.php)访问它。如果没有,请将它们重定向到页面的SSL版本。

实际上,我想让用户安全地使用该页面。

9 个答案:

答案 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
}
?>

http://php.net/manual/en/reserved.variables.server.php

答案 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]