Как узнать, используете ли вы HTTPS без $ _SERVER

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

Чтобы быть ясным, в настоящее время я использую этот код для разрешения, если это HTTPS-соединение:

 if(isset($_SERVER['HTTPS'])) { if ($_SERVER['HTTPS'] == "on") { $secure_connection = true; } } 

Chacha, согласно документации PHP: «Задайте непустое значение, если скрипт был запрошен через протокол HTTPS». Таким образом, оператор if будет возвращать false во многих случаях, когда HTTPS действительно включен. Вы хотите проверить, что $_SERVER['HTTPS'] существует и не является пустым. В случаях, когда HTTPS установлен неправильно для данного сервера, вы можете попробовать проверить, существует ли $_SERVER['SERVER_PORT'] == 443 .

Но обратите внимание, что некоторые серверы также будут устанавливать $_SERVER['HTTPS'] на непустое значение, поэтому обязательно проверьте эту переменную.

Ссылка: Документация для $_SERVER и $HTTP_SERVER_VARS [устарела]

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

 function isSecure() { return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443; } 

Код совместим с IIS.

Из документации PHP.net и комментариев пользователей :

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

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

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

Мое решение (поскольку стандартные условия [$ _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 http: //en.wikipedia. орг / вики / List_of_HTTP_header_fields # Common_non-standard_request_headers

 if( (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || $_SERVER['SERVER_PORT'] == 443 ){ //enable secure connection } 

У меня только что была проблема, когда я запускал сервер с помощью Apache mod_ssl, но phpinfo () и var_dump ($ _SERVER) показали, что PHP все еще думает, что я на порту 80.

Вот мое обходное решение для тех, кто с тем же вопросом …

 <VirtualHost *:443> SetEnv HTTPS on DocumentRoot /var/www/vhost/scratch/content ServerName scratch.example.com </VirtualHost> 

Стоит отметить строку SetEnv. После этого на месте и после перезагрузки вы должны иметь переменную окружения HTTPS, о которой вы всегда мечтали

Если вы используете Apache, вы всегда можете рассчитывать на

 $_SERVER["REQUEST_SCHEME"] 

для проверки схемы запрашиваемого URL. Но, как упоминалось в других ответах, разумно проверить другие параметры, прежде чем использовать SSL.

РЕАЛЬНЫЙ ответ: готов к копированию в скрипт [config]

 / * настройки конфигурации;  X = редактировать может 10th '11 * /
 $ Pv_sslport = 443;  / * поскольку это может быть иначе, как и Габриэль Соса *
 $ Pv_serverport = 80;  /* ИКС */
 $ Pv_servername = "mysite.com";  /* ИКС */

 / * X, добавленный после исправления Майклом Копиньским * /
 if (! isset ($ _ SERVER ["SERVER_NAME"]) ||! $ _ SERVER ["SERVER_NAME"]) {
     if (! isset ($ _ ENV ["SERVER_NAME"])) {
         GETENV ( "ИМЯ_СЕРВЕР");
         // Установить в 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, поскольку это прямая копия-паста, которая всегда будет работать. Эта часть может использоваться в сценарии производства.

Я не думаю, что добавление порта – хорошая идея – особенно когда у вас много серверов с разными сборками. это просто добавляет еще одну вещь, которую нужно помнить, чтобы ее изменить. глядя на doc, я думаю, что последняя линия кайзеров неплоха, так что:

 if(!empty($_SERVER["HTTPS"])) if($_SERVER["HTTPS"]!=="off") return 1; //https else return 0; //http else return 0; //http 

кажется вполне достаточно.

Я нахожу эти параметры приемлемыми, а также, скорее всего, не имеют ложных срабатываний при переключении веб-серверов.

  1. $ _SERVER [ 'HTTPS_KEYSIZE']
  2. $ _SERVER [ 'HTTPS_SECRETKEYSIZE']
  3. $ _SERVER [ 'HTTPS_SERVER_ISSUER']
  4. $ _SERVER [ 'HTTPS_SERVER_SUBJECT']

     if($_SERVER['HTTPS_KEYSIZE'] != NULL){/*do foobar*/} 

Вы можете проверить $_SERVER['SERVER_PORT'] поскольку SSL обычно работает на порту 443, но это не является надежным.

Единственным надежным методом является метод, описанный Игорем М.

 $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://"); 

Рассмотрим следующее: вы используете nginx с fastcgi, по умолчанию (debian, ubuntu) fastgi_params содержат директиву:

fastcgi_param HTTPS $ https;

если вы НЕ используете SSL, он будет переведен как пустое значение, а не «выключено», а не 0, и вы обречены.

http://unpec.blogspot.cz/2013/01/nette-nginx-php-fpm-redirect.html

Самый короткий путь, который я использую:

 $secure_connection = !empty($_SERVER['HTTPS']); 

Если используется https, то $ secure_connection истинно.

На моем сервере (Ubuntu 14.10, Apache 2.4, php 5.5) переменная $_SERVER['HTTPS'] не установлена, когда PHP-скрипт загружается через https. Я не знаю, что не так. Но следующие строки в файле .htaccess исправляют эту проблему:

 RewriteEngine on RewriteCond %{HTTPS} =on [NC] RewriteRule .* - [E=HTTPS:on,NE] 

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

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

 /** * Determine if this is a secure HTTPS connection * * @return bool True if it is a secure HTTPS connection, otherwise 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; } 

Что ты думаешь об этом?

 if (isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') $scheme = 'https'; else $scheme = 'http'; 

просто для интереса, хром канарейка в данный момент отправляет

 HTTPS : 1 

на сервер и в зависимости от того, как настроен сервер, может означать, что вы возвращаете следующее

 HTTPS : 1, on 

Это нарушило наше приложение, потому что мы тестировали, если он включен, чего, очевидно, нет. На данный момент кажется, что это только хром канарейка, но стоит отметить, что вещи у канарейки обычно приземляются в «нормальном» хроме вскоре.

Если вы используете nginx в качестве системы балансировки, проверьте $ _SERVER ['HTTP_HTTPS'] == 1 другие проверки будут сбой для ssl.

Если вы используете балансировщик нагрузки Incapsula, вам необходимо использовать IRule для создания настраиваемого заголовка для вашего сервера. Я создал заголовок HTTP_X_FORWARDED_PROTO, который равен либо «http», если для порта установлено значение 80 и «https», если оно равно 443.

 $secure_connection = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || (!empty($_SERVER['HTTP_HTTPS']) && $_SERVER['HTTP_HTTPS'] != 'off') || $_SERVER['REQUEST_SCHEME'] == 'https' || $_SERVER['SERVER_PORT'] == 443) ? true : false; 

Код проверяет все возможное и работает также на веб-сервере IIS. Chrome, так как v44 не устанавливает заголовок HTTP: 1, поэтому проверка HTTP_HTTPS в порядке. Если этот код не соответствует https, это означает, что ваш веб-сервер или прокси-сервер плохо настроены. Apache сам устанавливает флаг HTTPS правильно, но может возникнуть проблема при использовании прокси-сервера (например, nginx). Вы должны установить некоторый заголовок в виртуальном хосте nginx https

 proxy_set_header X-HTTPS 1; 

и используйте некоторый модуль Apache, чтобы правильно установить флаг HTTPS, ища X-HTTPS из прокси. Поиск mod_fakessl, mod_rpaf и т. Д.

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

 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; } 

Предоставление моей функции функции чтения всех предыдущих сообщений:

 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; } 

По сообщению hobodave: «Задайте непустое значение, если скрипт был запрошен через протокол HTTPS».

 if (!empty($_SERVER['HTTPS'])) { $secure_connection = true; }