PHP https проверить с помощью гибкого ssl (cloudflare), как это сделать?

Справочная информация: веб-сайт (example.com), настройка DNS через прокси-план Cloudflare, предлагает "гибкий ssl" (здесь), что означает, что ssl существует только между клиентом и облачным флагом, а не между облачным флагом и сервером, поэтому ему не нужен выделенный ip и не требуется специальных настроек на сервере. Сервер настроен на то, чтобы не использовать ssl (просто общий веб-сайт), однако cloudflare flexible ssl заботится о аспекте ssl.

Язык: PHP (codeignighter, но это действительно не имеет значения)

Цель: при просмотре в домене "exmple.com/" или "http://exmple.com/" сгенерировать переменную "http://example.com" и при просмотре на "https://example.com/*" для генерации переменной "https://example.com".

Что должно работать (но не работает):

$root = '';
if( isset($_SERVER['HTTPS'] )  && $_SERVER['HTTPS'] != 'off' )
{
    //it doesnt reach here...
    $root .= 'https://';
}
else
{
    $root .= 'http://';
}
$root  .= "".$_SERVER['HTTP_HOST'];
$root .= str_replace(basename($_SERVER['SCRIPT_NAME']),"",$_SERVER['SCRIPT_NAME']);

Я всегда могу сделать так: "//example.com", но это действительно не решает проблему для меня. Мысли? Должен ли я выполнять некоторое сравнение строк для определения https-ness?

Я уверен, что причина этого в том, что запрос достигает сервера (https или http), он поступает через порт 80, и он не распознается как ssl, поэтому $_SERVER ['HTTPS'] не определен. Я мог бы настроить пользовательский ssl между сервером и облачным флером, но был бы лучше (меньше усилий), если бы я мог просто использовать некоторое регулярное выражение и каким-то образом сравнить URL-адрес.

Я также хотел бы знать возможные проблемы и уязвимости.

Спасибо:)

Ответ 1

Хорошо, я отвечу на свой вопрос для будущих людей, у которых есть такая же проблема:

if(!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])){
    $root .= $_SERVER['HTTP_X_FORWARDED_PROTO'].'://';
}
else{
    $root .= !empty($_SERVER['HTTPS']) ? "https://" : "http://";
}

Пришел к нему, когда я внимательно смотрел на $_SERVER и искал поиск по HTTP_X_FORWARDED_PROTO и получил меня на несколько страниц, которые подтвердили это.

Ответ 2

$_SERVER['HTTP_X_FORWARDED_PROTO'] не работает для меня. Я не знаю почему. В любом случае, здесь мое решение:

function is_https_buttflare() {
    return isset($_SERVER['HTTPS']) ||
        ($visitor = json_decode($_SERVER['HTTP_CF_VISITOR'])) &&
            $visitor->scheme == 'https';
}

Ответ 3

Он работает на меня без проблем. Вы можете использовать в любом месте:

function is_ssl_active() {
  if (isset($_SERVER['HTTP_CF_VISITOR'])) {
    $cf_visitor = json_decode($_SERVER['HTTP_CF_VISITOR']);
    if (isset($cf_visitor->scheme) && $cf_visitor->scheme == 'https') {
      return true;
    }
  } else if (isset($_SERVER['HTTPS'])) {
    return true;
  }
  return false;
}

Cloudflare помещает некоторые HTTP-заголовки, такие как "CF-Visitor". Нажмите здесь, чтобы узнать больше.

Ответ 4

Я столкнулся с той же проблемой, когда я не мог получить переменную $_SERVER [ "HTTPS" ], которая появляется при выполнении var_dump ($ _ SERVER). В CloudFlare есть три параметра SSL (гибкий SSL, полный SSL и полный SSL (строгий). Для серверов с самоподписанные сертификаты, рекомендуется использовать полный SSL. После того, как я изменил свои настройки на Full SSL, появилась переменная $_SERVER [ "HTTPS" ], а $_SERVER [ "SERVER_PORT" ] изменилась с 80 на 443. Теперь я могу проверить, является ли моя страница HTTPS или не намного проще, например это:

public function get_https_status() {
    return isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on' ?
        true : false;
}

До обнаружения этих изменений я полагался на $_SERVER [ "HTTP_CF_VISITOR" ] и проверял схему, все это отлично работало при доступе к странице через общедоступный IP-адрес, но при обращении к странице локально, другими словами, localhost "в качестве URL-адреса, $_SERVER [" HTTP_CF_VISITOR "] не существовало, но $_SERVER [" HTTPS "] сделал... Поэтому моя проблема заключалась в доступе к странице через общедоступный IP-адрес, $_SERVER [" HTTPS "] не отображался, а $_SERVER [ "HTTP_CF_VISITOR" ]. И наоборот.

Ответ 5

Я сделал это, чтобы проверить все результаты:

        // check if ssl used on server
        if ( (!empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' ) || $_SERVER['SERVER_PORT'] == 443 ){

            echo '<script>console.log("https")</script>';

        //check if ssl used on load balancers such as cloudflare
        }elseif ( !empty( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' ) {

            echo '<script>console.log("https")</script>';

        }else{

            echo '<script>console.log("http")</script>';

        }

Ответ 6

Вы пытались проверить переменную $_SERVER ['SERVER_PORT']? Это должно вернуть "80", если это просто HTTP-соединение, или "443", если вы используете HTTPS-соединение.

Таким образом, мы надеемся, что такая функция будет работать:

function get_http()
{
    if ($_SERVER['SERVER_PORT'] == '443')
    {
        return 'https';
    }

    return 'http';
}