Как я могу заставить пользователей обращаться к моей странице по HTTPS вместо HTTP?

У меня есть только одна страница, к которой я хочу принудительно обращаться как к странице HTTPS (PHP на Apache). Как мне сделать это, не требуя HTTPS для всего каталога? Или, если вы отправляете форму на страницу HTTPS со страницы HTTP, отправляет ли она ее по HTTPS вместо HTTP?

Вот мой пример:

http://www.example.com/some-page.php

Я хочу, чтобы к нему можно было получить доступ только через:

https://www.example.com/some-page.php

Конечно, я могу поместить все ссылки на эту страницу, указывающие на версию HTTPS, но это не останавливает какого-то дурака от намеренного доступа к ней через HTTP ...

Одна вещь, которую я подумал, - это поместить перенаправление в заголовок файла PHP, чтобы убедиться, что они получают доступ к версии HTTPS:

if ($_SERVER["SCRIPT_URI"] == "http://www.example.com/some-page.php"){
  header('Location: https://www.example.com/some-page.php');
}

Но это ведь не может быть правильным путем?

Есть ли причина, по которой вам просто не требуется SSL для всех страниц?

The Tahaan 10.05.2015 21:45
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
139
2
177 036
22

Ответы 22

Вы можете сделать это с помощью директивы и mod_rewrite на Apache:

<Location /buyCrap.php>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
</Location>

Вы можете со временем сделать Location более умным, используя обычные выражения, если хотите.

Куда бы вы это положили? .htaccess файл?

Wiki 17.09.2008 22:16

Разве REQUEST_URI не включает «строку запроса» (например,? Page = 1 & id = 41 и т. д.)? Это то, что говорится в документации apache ... Так что, если я попытаюсь получить доступ к site.com/index.php?page=1&id=12, я буду перенаправлен на site.com/index.php

Rolf 08.07.2013 17:00

Из документации apache: REQUEST_URI Компонент пути запрошенного URI, например "/index.html". Это, в частности, исключает строку запроса, которая доступна как собственная переменная с именем QUERY_STRING. Поэтому вам нужно добавить QUERY_STRING после REQUEST_URI

Rolf 08.07.2013 17:03

Вам также необходимо добавить флаг [R] после этого, чтобы перенаправить

Rolf 08.07.2013 17:17

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

И помните, что страницу, на которой отображается форма, не нужно загружать через HTTPS, это URL-адрес обратной отправки, который больше всего в этом нуждается.

Редактировать: да, как указано ниже, лучше всего иметь весь процесс в HTTPS. Это намного обнадеживает - я указывал на то, что пост - самая важная часть. Кроме того, вам необходимо позаботиться о том, чтобы все файлы cookie были безопасными, поэтому они будут отправляться только через SSL. Решение mod_rewrite также очень изящное, я использовал его для защиты множества приложений на моем собственном веб-сайте.

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

Graeme Perrow 17.09.2008 22:02

@Graeme: кроме того, никто не может быть уверен, что форма когда-либо будет отправлена ​​через https. Вся форма (отображаемая через http) может быть подделкой, отправленной на неизвестный сайт или сайт с открытым текстом http. Https - это не только шифрование, но и проверка подлинности сервера.

Olaf Kock 30.09.2008 00:02

То, как я делал это раньше, в основном похоже на то, что вы написали, но не имеет жестко запрограммированных значений:

if ($_SERVER["HTTPS"] != "on")
{
    header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
    exit();
}

Вы забыли вызвать exit (), чтобы гарантировать завершение работы сценария после перенаправления. Я обычно заключаю это в функцию под названием requireSSL (). Я могу назвать это вверху любой страницы, которую я хочу зашифровать.

Jesse Weigert 13.01.2009 14:20

Измените if на (empty($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] !== "on"), чтобы исправить уведомления PHP.

dave1010 30.01.2013 18:57

Разве переменные $_SERVER[] не изменяются / не уязвимы для вмешательства пользователей?

Arian Faurtosh 07.05.2014 10:48

Источник @ArianFaurtosh?

John 08.03.2016 10:47

@ArianFaurtosh, некоторые из них извлекаются из заголовков клиентов, например HTTP_X_FORWARDED, и ими можно управлять, но другие, такие как HTTPS или SERVER_PORT, устанавливаются непосредственно с веб-сервера и должны быть безопасными для обычно.

Mahn 23.06.2016 06:36

Я объединил это с ответом temuraru от stackoverflow.com/a/16076965/1040123, чтобы проверить https на серверах за балансировщиком нагрузки.

odaa 04.04.2017 21:32

Не смешивайте HTTP и HTTPS на одной странице. Если у вас есть страница формы, которая обслуживается через HTTP, я буду нервничать по поводу отправки данных - я не могу увидеть, идет ли отправка через HTTPS или HTTP, не выполняя просмотр источника и не ища его.

Обслуживание формы через HTTPS вместе со ссылкой для отправки - не такое уж серьезное изменение для преимущества.

Не следует из соображений безопасности. Особенно, если здесь используются куки. Это оставляет вас широко открытыми для атак с использованием файлов cookie.

В любом случае вы должны использовать правила управления Apache для его настройки.

Затем вы можете проверить, включен ли HTTPS, и при необходимости перенаправить его.

Вы должны перенаправлять на страницу оплаты только с помощью FORM POST (без получения), и доступ к странице без POST должен быть направлен обратно на другие страницы. (Это заставит людей просто прыгать по горячим следам.)

http://joseph.randomnetworks.com/archives/2004/07/22/redirect-to-ssl-using-apaches-htaccess/

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

Это чрезмерно защищает, но, по крайней мере, у вас меньше забот.

// Force HTTPS for security
if ($_SERVER["HTTPS"] != "on") {
    $pageURL = "Location: https://";
    if ($_SERVER["SERVER_PORT"] != "80") {
        $pageURL .= $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"];
    } else {
        $pageURL .= $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"];
    }
    header($pageURL);
}

Вы должны заставить клиент запрашивать HTTPS всегда с заголовками Строгая безопасность транспорта HTTP (HSTS):

// Use HTTP Strict Transport Security to force client to use secure connections only
$use_sts = true;

// iis sets HTTPS to 'off' for non-SSL requests
if ($use_sts && isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') {
    header('Strict-Transport-Security: max-age=31536000');
} elseif ($use_sts) {
    header('Location: https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'], true, 301);
    // we are in cleartext at the moment, prevent further execution and output
    die();
}

Обратите внимание, что HSTS поддерживается в большинстве современных браузеров, но не универсален. Таким образом, приведенная выше логика вручную перенаправляет пользователя независимо от поддержки, если они заканчиваются на HTTP, а затем устанавливает заголовок HSTS так, чтобы дальнейшие клиентские запросы по возможности перенаправлялись браузером.

Я удивлен, что ни один из других ответов не включает этот заголовок, это довольно важно ... есть ли ловушка для объединения двух из них?

keisar 19.04.2013 01:23

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

Jacob Swartwood 26.04.2013 03:24

(Редактирование исходного комментария) Я не заметил особого требования «всего одна страница». HSTS будет применяться ко всем страницам; мой ответ технически неверен.

Jacob Swartwood 26.04.2013 03:32

К вашему сведению, в стандартном разделе 7.2 RFC 6797 говорится: «Хост HSTS НЕ ДОЛЖЕН включать поле заголовка STS в HTTP-ответы, передаваемые по незащищенному транспорту». поэтому нет необходимости отправлять его, если запрос является обычным http, его следует игнорировать, если браузер соответствует стандарту.

Frank Forte 24.11.2013 08:56

С точки зрения безопасности, я считаю, что это лучший ответ. Однако я бы не стал делать никаких перенаправлений. Просто включите HSTS или заблокируйте загрузку страницы.

Alex W 30.11.2015 18:56

@AlexW Спасибо за ваш вклад. Почему бы не перенаправить?

Mark 09.02.2016 22:29

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

M H 16.01.2017 23:48

@mark, если есть MITM и на вашем веб-сайте нет этого заголовка, вы можете разрешить входящему в состав сеансу перейти на http, и люди будут вводить свои данные, и они, вероятно, не заметят, и перенаправление не поможет (человек в средний будет подключаться к сайту через https и представлять его как http). Использование этого заголовка приведет к принудительному использованию HTTPS на стороне клиента. Это особенно важно из-за недавней уязвимости безопасности WPA2 WiFi.

Rudiger 17.10.2017 08:28

http://www.besthostratings.com/articles/force-ssl-htaccess.html

Иногда вам может потребоваться убедиться, что пользователь просматривает ваш сайт через защищенное соединение. Простой способ всегда перенаправлять пользователя на безопасное соединение (https: //) может быть реализован с помощью файла .htaccess, содержащего следующие строки:

RewriteEngine On 
RewriteCond %{SERVER_PORT} 80 
RewriteRule ^(.*)$ https://www.example.com/ [R,L]

Обратите внимание, что .htaccess должен находиться в основной папке сайта.

Если вы хотите принудительно использовать HTTPS для определенной папки, вы можете использовать:

RewriteEngine On 
RewriteCond %{SERVER_PORT} 80 
RewriteCond %{REQUEST_URI} somefolder 
RewriteRule ^(.*)$ https://www.domain.com/somefolder/ [R,L]

Файл .htaccess нужно поместить в папку, в которой нужно принудительно включить HTTPS.

<?php 
// Require https
if ($_SERVER['HTTPS'] != "on") {
    $url = "https://". $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
    header("Location: $url");
    exit;
}
?>

Это просто.

Приходилось делать что-то подобное при работе за балансировщиком нагрузки. Наконечник шляпы https://stackoverflow.com/a/16076965/766172

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

function requireHTTPS() {
    if (!isSecure()) {
        header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], TRUE, 301);
        exit;
    }
}

Хорошо ... Сейчас об этом много всего, но никто на самом деле не завершает «Безопасный» вопрос. Для меня смешно использовать что-то небезопасное.

Если только вы не используете его как приманку.

Распространение $ _SERVER может быть изменено по желанию того, кто знает как.

Также, как заявили Сазад Тушар Хан и thebigjc, вы также можете использовать httaccess для этого, и здесь есть много ответов, содержащих его. Просто добавьте:

RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://example.com/ [R,L]

до конца того, что у вас есть в вашем .httaccess, и это все.

Тем не менее, с этими двумя инструментами мы не настолько защищены, насколько это возможно.

В остальном все просто. Если отсутствуют атрибуты, то есть ...

if (empty($_SERVER["HTTPS"])){ // SOMETHING IS FISHY
}

if (strstr($_SERVER['HTTP_HOST'],"mywebsite.com") === FALSE){// Something is FISHY
}


Также скажите, что вы обновили файл httaccess и проверяете:

if ($_SERVER["HTTPS"] !== "on"){// Something is fishy
}

Есть еще много переменных, которые вы можете проверить, например ..

HOST_URI(Если есть статические атрибуты для проверки)

HTTP_USER_AGENT(Одинаковая сессия, разные значения)

Так что все, что я говорю, это не соглашайтесь на одно или другое, когда ответ заключается в комбинации. Для получения дополнительной информации о перезаписи httaccess см. Docs-> http://httpd.apache.org/docs/2.0/misc/rewriteguide.html

Некоторые стеки здесь -> Принудительно использовать SSL / https с помощью .htaccess и mod_rewrite
и
Получение полного URL-адреса текущей страницы (PHP)
назвать пару.

но теперь я получаю следующую ошибку: ERR_TOO_MANY_REDIRECTS. Как я могу это исправить?

Pathros 16.03.2016 08:39

Я только что создал файл .htaccess и добавил:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

Простой !

Я использовал этот скрипт, и он хорошо работает через сайт.

if (empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == "off"){
    $redirect = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
    enter code hereheader('HTTP/1.1 301 Moved Permanently');
    header('Location: ' . $redirect);
    exit();
}

Если вы используете Apache или что-то вроде LiteSpeed, которое поддерживает файлы .htaccess, вы можете сделать следующее. Если у вас еще нет файла .htaccess, вам следует создать новый файл .htaccess в корневом каталоге (обычно там, где находится ваш index.php). Теперь добавьте эти строки в качестве первых правил перезаписи в свой .htaccess:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Вам понадобится только один раз инструкция "RewriteEngine On" в вашем .htaccess для всех правил перезаписи, поэтому, если она у вас уже есть, просто скопируйте вторую и третью строку.

Надеюсь, это поможет.

Это то, что у меня сработало, и то, что я использую в своих собственных скриптах на платформе, подобной Zend 2, - я не понимаю, что такое отрицательное голосование.

Antonio 02.11.2016 23:25

Может быть, вас проголосовали против, потому что ответ практически такой же, как Вот этот от @MatHatrik, который был опубликован более года назад?

Wilt 24.01.2017 11:19

Недостаточно использовать это:

if ($_SERVER["HTTPS"] != "on")
{
    header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
    exit();
}

Если у вас есть какой-либо http-контент (например, внешний источник http-изображения), браузер обнаружит возможную угрозу. Поэтому убедитесь, что все ваши ref и src внутри вашего кода https

Я прошел через множество решений с проверкой статуса $ _SERVER [HTTPS], но кажется, что он ненадежен, потому что иногда он не устанавливается или не включается, выключается и т. д., Вызывая перенаправление скрипта во внутренний цикл.

Вот самое надежное решение, если ваш сервер поддерживает $ _SERVER [SCRIPT_URI]

if (stripos(substr($_SERVER[SCRIPT_URI], 0, 5), "https") === false) {
    header("location:https://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]");
    echo "<meta http-equiv='refresh' content='0; url=https://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]'>";
    exit;
}

Обратите внимание, что в зависимости от вашей установки ваш сервер может не поддерживать $ _SERVER [SCRIPT_URI], но если он поддерживает, лучше использовать этот сценарий.

Вы можете проверить здесь: Почему в некоторых установках PHP есть $ _SERVER ['SCRIPT_URI'], а в других нет

Для тех, кто использует IIS, добавление этой строки в web.config поможет:

<httpProtocol>
    <customHeaders>
        <add name = "Strict-Transport-Security" value = "max-age=31536000"/>
    </customHeaders>
</httpProtocol>
<rewrite>
    <rules>
        <rule name = "HTTP to HTTPS redirect" stopProcessing = "true">
              <match url = "(.*)" />
              <conditions>
                 <add input = "{HTTPS}" pattern = "off" ignoreCase = "true" />
              </conditions>
              <action type = "Redirect" redirectType = "Found" url = "https://{HTTP_HOST}/{R:1}" />
         </rule>
    </rules>
</rewrite>

Полный пример файла

<?xml version = "1.0" encoding = "UTF-8"?>
<configuration>
    <system.webServer>
        <httpProtocol>
            <customHeaders>
                <add name = "Strict-Transport-Security" value = "max-age=31536000"/>
             </customHeaders>
        </httpProtocol>
        <rewrite>
            <rules>
                <rule name = "HTTP to HTTPS redirect" stopProcessing = "true">
                      <match url = "(.*)" />
                      <conditions>
                         <add input = "{HTTPS}" pattern = "off" ignoreCase = "true" />
                      </conditions>
                      <action type = "Redirect" redirectType = "Found" url = "https://{HTTP_HOST}/{R:1}" />
                 </rule>
            </rules>
       </rewrite>
   </system.webServer>
</configuration>

Вопрос конкретно касается Apache, а не IIS.

Quentin 06.04.2017 13:10

А) это немаркированный apache. Apache указывается в кавычках. Б) это общий вопрос, который не имеет ничего общего с apache в целом. Это применимо к нескольким веб-серверам, поддерживающим php

Tschallacka 06.04.2017 13:13

используйте htaccess:

#if domain has www. and not https://
  RewriteCond %{HTTPS} =off [NC]
  RewriteCond %{HTTP_HOST} ^(?i:www+\.+[^.]+\.+[^.]+)$
  RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [QSA,L,R=307]

#if domain has not www.
  RewriteCond %{HTTP_HOST} ^([^.]+\.+[^.]+)$
  RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [QSA,L,R=307]

может быть, это может помочь, тебе, вот как я сделал для своего сайта, он работает как шарм:

$protocol = $_SERVER["HTTP_CF_VISITOR"];

if (!strstr($protocol, 'https')){
    header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
    exit();
}

Способ PHP:

$is_https=false;
if (isset($_SERVER['HTTPS'])) $is_https=$_SERVER['HTTPS'];
if ($is_https !== "on")
{
    header("Location: https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
    exit(1);
}

Способ Apache mod_rewrite:

RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Я предпочитаю PHP, потому что есть экземпляры, в которых я хочу переопределить требование SSL. Например, локальный доступ к API и вещам вроде автоконфигурации Mozilla Thunderbird и т. д.

Jay 27.10.2018 01:51

Метод PHP отлично работает для меня, очень рекомендуется.

Moxet Jan 31.01.2020 13:57

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


<?php

if (!isset($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] != "on") {
    header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"], true, 301);
    //Prevent the rest of the script from executing.
    exit;
}
?>

Он проверяет переменную HTTPS в суперглобальном массиве $ _SERVER, чтобы убедиться, что она равна «on». Если переменная не равна on.

В качестве альтернативы вы можете использовать заголовок X-Forwarded-Proto для принудительного перенаправления на HTTPS.

добавьте эти строки в файл .htaccess

### Force HTTPS
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

это также исправило проблему Слишком много перенаправлений

Sumithran 04.01.2021 18:08

Другие вопросы по теме