Web

Как узнать, используется ли HTTPS без определения $_SERVER ['HTTPS']

Я видел много руководств в интернете, в которых говорится, что нужно проверить $_SERVER['HTTPS'], если соединение с сервером защищено HTTPS. Моя проблема в том, что на некоторых серверах, которые я использую, $_SERVER['HTTPS'] является неопределенной переменной, что приводит к ошибке. Есть ли другая переменная, которую я могу проверить и которая всегда должна быть определена? Для ясности, в настоящее время я использую этот код, чтобы определить, является ли это соединение HTTPS:

if(isset($_SERVER['HTTPS'])) {

    if ($_SERVER['HTTPS'] == "on") {

        $secure_connection = true;

    }

}

 

Ответ 1

Это должно работать всегда, даже если $_SERVER['HTTPS'] не определен:

function isSecure() {

  return

    (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')

    || $_SERVER['SERVER_PORT'] == 443;

}

 Код совместим с IIS. Из документации PHP.net:

  1. Устанавливается в непустое значение, если скрипт был запрошен по протоколу HTTPS.

  2. Обратите внимание, что при использовании ISAPI с IIS значение будет «off», если запрос был сделан не по протоколу HTTPS таком же поведении сообщалось для IIS7, на котором PHP работает как приложение Fast-CGI).

Кроме того, серверы Apache 1.x могут не иметь определенного значения $_SERVER['HTTPS'] даже при безопасном соединении. Хотя это и не гарантировано, соединения через порт 443, по общему правилу, скорее всего, используют защищенные сокеты, поэтому и нужна дополнительная проверка порта.

Дополнительное замечание: если между клиентом и вашим сервером установлен балансировщик нагрузки, этот код проверяет не соединение между клиентом и балансировщиком нагрузки, а соединение между балансировщиком нагрузки и вашим сервером. Чтобы проверить первое соединение, вам придется проверить его с помощью заголовка HTTP_X_FORWARDED_PROTO, но это гораздо сложнее.

 

Ответ 2

Мое решение (поскольку стандартные условия [$_SERVER['HTTPS'] == 'on'] не работают на серверах с балансировщиком нагрузки) таково:

$isSecure = false;

if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {

    $isSecure = true;

}

elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' || !empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') {

    $isSecure = true;

}

$REQUEST_PROTOCOL = $isSecure ? 'https' : 'http';

 HTTP_X_FORWARDED_PROTO: стандарт де-факто для определения протокола происхождения HTTP-запроса, поскольку обратный прокси-сервер (балансировщик нагрузки) может взаимодействовать с веб-сервером, используя HTTP, даже если запрос к обратному прокси является HTTPS.



Ответ 3

Я сделал свою собственную функцию, прочитав все предыдущие ответы:

public static function isHttps() {

    if (array_key_exists("HTTPS", $_SERVER) && 'on' === $_SERVER["HTTPS"]) {

        return true;

    }

    if (array_key_exists("SERVER_PORT", $_SERVER) && 443 === (int)$_SERVER["SERVER_PORT"]) {

        return true;

    }

    if (array_key_exists("HTTP_X_FORWARDED_SSL", $_SERVER) && 'on' === $_SERVER["HTTP_X_FORWARDED_SSL"]) {

        return true;

    }

    if (array_key_exists("HTTP_X_FORWARDED_PROTO", $_SERVER) && 'https' === $_SERVER["HTTP_X_FORWARDED_PROTO"]) {

        return true;

    }

    return false;

}

 

Ответ 4

Мой ответ готов для копирования-вставки в скрипт [config]:

/* параметры конфигурации */

$pv_sslport=443; 

$pv_serverport=80; /* X */

$pv_servername="mysite.com"; /* X */

/* X добавлено после исправления */

if(!isset($_SERVER["SERVER_NAME"]) || !$_SERVER["SERVER_NAME"]) {

    if(!isset($_ENV["SERVER_NAME"])) {

        getenv("SERVER_NAME");

        // Установить в env имя_сервера

        $_SERVER["SERVER_NAME"]=$_ENV["SERVER_NAME"];

    }

}

if(!$_SERVER["SERVER_NAME"]) (

    /* Имя X-сервера все еще пустое? ... вы можете установить $_SERVER["SERVER_NAME"]=$pv_servername; */

}

if(!isset($_SERVER["SERVER_PORT"]) || !$_SERVER["SERVER_PORT"]) {

    if(!isset($_ENV["SERVER_PORT"])) {

        getenv("SERVER_PORT");

        $_SERVER["SERVER_PORT"]=$_ENV["SERVER_PORT"];

    }

}

if(!$_SERVER["SERVER_PORT"]) (

    /* Порт X-сервера все еще пуст? ... вы можете установить $_SERVER["SERVER_PORT"]=$pv_serverport; */

}

$pv_URIprotocol = isset($_SERVER["HTTPS"]) ? (($_SERVER["HTTPS"]==="on" || $_SERVER["HTTPS"]===1 || $_SERVER["SERVER_PORT"]===$pv_sslport) ? "https://" : "http://") :  (($_SERVER["SERVER_PORT"]===$pv_sslport) ? "https://" : "http://");

 Теперь $pv_URIprotocol корректен и готов к использованию; пример $site=$pv_URIprotocol.$_SERVER["SERVER_NAME"]. Естественно, строку можно заменить на TRUE и FALSE. PV означает PortalPress Variable, так как это прямая копия-вставка, которая всегда будет работать. Этот фрагмент можно использовать в производственном скрипте.

 

Ответ 5

Вот многократно используемая функция, которую я использую уже некоторое время.

Примечание: значение HTTPS_PORT (которое является пользовательской константой в моем коде) может меняться в зависимости от вашего окружения, например, она может быть 443 или 81.

/**

* Определите, является ли это безопасным HTTPS-соединением.

 * 

 * @return bool True, если это безопасное HTTPS-соединение, иначе false.

 */

function isSSL() {

    if (isset($_SERVER['HTTPS'])) {

        if ($_SERVER['HTTPS'] == 1) {

            return true;

        } elseif ($_SERVER['HTTPS'] == 'on') {

            return true;

        }

    } elseif ($_SERVER['SERVER_PORT'] == HTTPS_PORT) {

        return true;

    }

    return false;

}

 

Ответ 6

У меня есть возможность пойти дальше и определить, поддерживает ли сайт, к которому я подключаюсь, SSL (один проект запрашивает у пользователя его URL, и нам нужно проверить, установили ли они наш пакет API на http или https сайт). Вот функция, которую я использую,по сути, просто вызываем URL через cURL, чтобы проверить, работает ли https:

function hasSSL($url)  {

    // свести URL-адрес к доменному имени

    $domain = parse_url($url, PHP_URL_HOST);

    $ch = curl_init('https://' . $domain);

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'HEAD'); // это HEAD

    curl_setopt($ch, CURLOPT_NOBODY, true);          // без тела 

    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);  // в случае перенаправления

    curl_setopt($ch, CURLOPT_VERBOSE, 0); //включить при отладке

    curl_setopt($ch, CURLOPT_HEADER, 1);     // требуются только заголовки

    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);    // мы не хотим ждать долго

    curl_exec($ch);

    $header = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    if ($header === 200) {

        return true;

    }

    return false;

}

 Это самый надежный способ, который я нашел, чтобы не только узнать, используете ли вы https (как спрашивается в вопросе), но и МОЖЕТЕ ли вы (или даже ДОЛЖНЫ ли) использовать https.

ПРИМЕЧАНИЕ: возможно (хотя и маловероятно...), что на сайте могут быть разные http и https страницы (так что, если вам говорят использовать http, возможно, вам не нужно менять запрос...). Подавляющее большинство сайтов одинаковы и, вероятно, должны перенаправлять вас сами, но эта дополнительная проверка имеет свое применение (конечно, как я уже сказал, в проекте, где пользователь вводит информацию о своем сайте, и вы хотите убедиться в этом на стороне сервера).

 

Ответ 7

Если у вас нет контроля над веб-сервером и вы не знаете, какие переменные были установлены, загрузите этот php, чтобы узнать это:

<?php

echo "<br>1 ".$_SERVER["HTTPS"];

echo "<br>2 ".$_SERVER["SERVER_PORT"];

echo "<br>3 ".$_SERVER["HTTP_X_FORWARDED_PROTO"];

echo "<br>4 ".$_SERVER["HTTP_X_FORWARDED_SSL"];

echo "<br>5 ".$_SERVER["HTTP_HTTPS"];

echo "<br>6 ".$_SERVER["REQUEST_SCHEME"];

?>

 

<html>

<body>

<br>

Некоторый текст

</body>

</html>

 

 Ответ 8

Я бы добавил глобальный фильтр, чтобы убедиться, что все, что я проверяю, правильно:

function isSSL() {

    $https = filter_input(INPUT_SERVER, 'HTTPS');

    $port = filter_input(INPUT_SERVER, 'SERVER_PORT');

    if ($https) {

        if ($https == 1) {

            return true;

        } elseif ($https == 'on') {

            return true;

        }

    } elseif ($port == '443') {

        return true;

    }

    return false;

}

 

Схожие статьи

Web

Преобразование форматов даты в PHP

Web

Регулярное выражение с атрибутами шорткодов Wordpress

Web

Пример использования bind_result/get_result

Как поднять свой VPN сервер: пошаговая инструкция с картинками
Web

Как поднять свой VPN сервер: пошаговая инструкция с картинками

×