Я видел много обучающих онлайн, в которых говорится, что вам нужно проверить $_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
кажется вполне достаточно.
Я нахожу эти параметры приемлемыми, а также, скорее всего, не имеют ложных срабатываний при переключении веб-серверов.
$ _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; }