Wh1T3h4Ck5
Wh1T3h4Ck5

Reputation: 8509

How to detect secure connection (https) using PHP?

At the moment I have SSL included on my server. Want to force my users to login using login-page via https.

<?php

  if (empty($_SERVER['https']) || $_SERVER['https'] != 'on') {
    header('location: https://my_login_page');
    exit();
    }

  # rest of code
  ...

But it's a problem when there's no SSL.

Now I have situation. User requests following URL

http://domain.com/login.php

Here, I can't access to $_SERVER['https'] and want to make sure it's possible to redirect user to

https://domain.com/login.php

For example, SSL certificate expires after some time and want to keep users using login w/out secure connection.

My goal is something like this example:

if (ssl_installed() && (empty($_SERVER['https']) || $_SERVER[] != 'on')) {
  header('location: https://domain.com/login.php');
  exit();
  }

# when there's no SSL it continues using HTTP

Yes, want to write function (example: ssl_installed()) which returns true when it's possible using secure connection, otherwise false.

I've tried using get_headers() and realized it always returns false against https:// links.

Possible solution:

I already have working solution. Config table in my database contains row ssl=1 (or 0) and after database connection has been established I'm using this value to decide is there possible to use SSL or not and function mentioned above uses this value to return result.

My question is: Is there simpler solution?

To be clear: I'm looking for PHP-ONLY SOLUTION (auto-detection)!

Any help would be appreciated.

Upvotes: 0

Views: 10058

Answers (3)

anonystick
anonystick

Reputation: 362

/**
 * Return true if HTTPS enabled  otherwise return false
 */
function check_ssl() {
  if ( isset( $_SERVER['HTTPS'] ) ) {
    if ( 'on' == strtolower( $_SERVER['HTTPS'] ) ) {
      return true;
    } elseif ( '1' == $_SERVER['HTTPS'] ) {
      return true;
    }
  }

  if ( isset( $_SERVER['SERVER_PORT'] )
    && ( '443' == $_SERVER['SERVER_PORT'] ) 
  ) {
    return true;
  }

  return false;
}

Upvotes: 0

sjdaws
sjdaws

Reputation: 3536

You could do something like this in your config file rather than editing every script.

<?php

// will match /login.php and /checkout.php as examples
$force_ssl = preg_match('/\/(login|checkout)\.php(.+)?/', $_SERVER['REQUEST_URI']);
$using_ssl = (isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) ? true : false;

$url = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

if ($force_ssl && !$using_ssl) {

    // redirect to SSL
    header('Location: https://' . $url);

} elseif (!$force_ssl && $using_ssl) {

    // redirect back to normal
    header('Location: http://' . $url);

}

Then if your certificate expires, just set $force_ssl to false in your config file and it'll take care of every script which previously redirected.


Now the question has been clarified, you could create a PHP script like this (code taken from https://stackoverflow.com/a/4741196/654678)

<?php

// get and check certificate
$get = stream_context_create(array("ssl" => array("capture_peer_cert" => TRUE)));
$read = stream_socket_client("ssl://www.google.com:443", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $get);
$cert = stream_context_get_params($read);

$valid = ($cert["options"]["ssl"]["peer_certificate"] != NULL) ? true : false;

// save validity in database or somewhere else accessible

Then set up a crontab, or daily task or whatever to hit that PHP script daily. If there is no certificate, it'll return NULL and be marked as invalid. Check the validity with your script and you're good to go.

Upvotes: 5

NLZ
NLZ

Reputation: 945

I think you might solve this with htaccess and these two conditions might help

  • RewriteCond %{HTTP:X-Forwarded-SSL} on
  • RewriteCond %{HTTPS} on

For more info, see this answer: https://stackoverflow.com/a/1128624/1712686

Upvotes: 1

Related Questions