0

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.

Wh1T3h4Ck5
  • 8,399
  • 9
  • 59
  • 79
  • Do you have a generic config file within all the php files you use? Such as config.php? – sjdaws Feb 27 '13 at 09:21
  • @sjdaws Course yes, there I keep database-account info for using with PDO. – Wh1T3h4Ck5 Feb 27 '13 at 09:23
  • Is `$_SERVER["HTTPS"]` (capital letters) exists? [PHP doc](http://www.php.net/manual/en/reserved.variables.server.php) – Passerby Feb 27 '13 at 09:25
  • @Passerby - Works with both https and HTTPS on my server. But $_SERVER['HTTPS'] doesn't exist on HTTP request and doesn't tell me is it possible to redirect page to same using https:// instead of http://. – Wh1T3h4Ck5 Feb 27 '13 at 09:29

3 Answers3

5

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.

Community
  • 1
  • 1
sjdaws
  • 3,466
  • 16
  • 20
  • 2
    +1 for your effort. I already have similar solution which I use at the moment. I just was looking for a way to automatically determine SSL on the server, w/out setting SSL state manually (in config, database, etc). Btw, your line with $using_ssl assignment is incorrect because on IIS server $_SERVER['HTTPS'] is ALWAYS set to non-empty value ('on' or 'off') and it CAN'T BE EMPTY if set. – Wh1T3h4Ck5 Feb 27 '13 at 10:13
  • So you want PHP to detect whether a certificate installed on the server level? – sjdaws Feb 27 '13 at 10:15
  • Dirty solution, but still solution. Even, it's not exactly what I was actually looking for, bottom part of your answer helped me a lot to find solution (using cron). Thanks – Wh1T3h4Ck5 Feb 28 '13 at 09:49
  • You have a syntax error in the line "$using_ssl = (isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) ? true : false;" , you need to add another ")" before the "? true : false;" part, I cant edit it so I just let you know so you fix it – Miki Berkovich Jun 24 '15 at 07:59
1

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

Community
  • 1
  • 1
NLZ
  • 935
  • 6
  • 12
  • +1 Agree with you. Already seen this page. I'm just looking for PHP-only solution if possible. – Wh1T3h4Ck5 Feb 27 '13 at 09:26
  • http://stackoverflow.com/questions/14760493/detect-ssl-when-proxy-always-claims-a-secure-connection here you have client side redirect – Prabu Feb 27 '13 at 09:37
0
/**
 * 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;
}
anonystick
  • 362
  • 1
  • 9