Принудительное использование SSL / https с использованием .htaccess и mod_rewrite

Ответы:

438

Для Apache вы можете использовать mod_sslдля принудительного SSL с SSLRequireSSL Directive:

Эта директива запрещает доступ, если для текущего соединения не включен HTTP по SSL (т.е. HTTPS). Это очень удобно внутри виртуального хоста с поддержкой SSL или каталогов для защиты от ошибок конфигурации, которые представляют собой вещи, которые должны быть защищены. Когда эта директива присутствует, все запросы отклоняются, которые не используют SSL.

Это не будет делать перенаправление на https. Чтобы перенаправить, попробуйте следующее mod_rewriteв вашем .htaccess файле

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

или любой из различных подходов, данных на

Вы также можете решить эту проблему изнутри PHP в случае, если ваш провайдер отключил .htaccess (что маловероятно, так как вы просили об этом, но в любом случае)

if (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] !== 'on') {
    if(!headers_sent()) {
        header("Status: 301 Moved Permanently");
        header(sprintf(
            'Location: https://%s%s',
            $_SERVER['HTTP_HOST'],
            $_SERVER['REQUEST_URI']
        ));
        exit();
    }
}
Гордон
источник
1
Это прекрасно в нашей ситуации, потому что в настоящее время мы имеем смесь трафика http и https. Для нашей админки мы просто включили скрипт .htaccess, оставив остальную часть сайта http.
Майкл Дж. Калкинс
1
Когда я использую метод mod_rewrite, меня отправляют на https, но с ошибкой «Страница перенаправляется неправильно».
Чехнология
11
Продолжение: если у вас возникли аналогичные проблемы, проверьте сервер и переменные HTTP. Если ваш сервер использует прокси, вы можете использовать %{HTTP:X-Forwarded-Proto}или %{HTTP:X-Real-Port}переменные, чтобы проверить, включен ли SSL.
Чехнология
8
Если вы испытываете петли перенаправления на серверах, работающих за прокси ( CloudFlare , Openshift ), посмотрите этот ответ для решения, которое работает и для этого случая.
raphinesse
4
@GTodorov - Удаление места сломало переписывание для меня. Из моих (ограниченных) знаний о rewriterules, синтаксис есть RewriteRule <input-pattern> <output-url>. Таким образом, пространство должно быть там, и сингл ^просто говорит «соответствовать всем входным URL».
Sphinxxx
54

Я нашел mod_rewriteрешение, которое хорошо работает как для прокси, так и для прокси серверов.

Если вы используете CloudFlare, AWS Elastic Load Balancing, Heroku, OpenShift или любое другое решение Cloud / PaaS, и у вас возникают циклы перенаправления с обычными перенаправлениями HTTPS, попробуйте следующий фрагмент.

RewriteEngine On

# If we receive a forwarded http request from a proxy...
RewriteCond %{HTTP:X-Forwarded-Proto} =http [OR]

# ...or just a plain old http request directly from the client
RewriteCond %{HTTP:X-Forwarded-Proto} =""
RewriteCond %{HTTPS} !=on

# Redirect to https version
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
raphinesse
источник
Это великолепно, спасибо! Но, может быть, нужно добавить условие поста? RewriteCond% {REQUEST_METHOD}! ^ POST $
Алексей
@Aleksej Правда, это нарушает незашифрованные POST-запросы. Но я думаю, что это хорошо. Таким образом, люди заметят, что они делают что-то не так. Я думаю, что лучше всего было бы перенаправить их на страницу, которая информирует их о том, как правильно использовать ваш сервис.
рафинесс
@raphinesse Знаете ли вы ответ на этот вопрос: stackoverflow.com/questions/51951082/…
RRN
36

PHP решение

Заимствуя непосредственно из исчерпывающего ответа Гордона, я отмечаю, что в вашем вопросе упоминается, что он связан с конкретной страницей при форсировании HTTPS / SSL-соединений.

function forceHTTPS(){
  $httpsURL = 'https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
  if( count( $_POST )>0 )
    die( 'Page should be accessed with HTTPS, but a POST Submission has been sent here. Adjust the form to point to '.$httpsURL );
  if( !isset( $_SERVER['HTTPS'] ) || $_SERVER['HTTPS']!=='on' ){
    if( !headers_sent() ){
      header( "Status: 301 Moved Permanently" );
      header( "Location: $httpsURL" );
      exit();
    }else{
      die( '<script type="javascript">document.location.href="'.$httpsURL.'";</script>' );
    }
  }
}

Затем, как можно ближе к верхней части этих страниц, которые вы хотите принудительно подключить через PHP, вы можете require()централизованный файл, содержащий эту (и любые другие) пользовательские функции, а затем просто запустить forceHTTPS()функцию.

HTACCESS / mod_rewrite Решение

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

RewriteEngine on

# Check for POST Submission
RewriteCond %{REQUEST_METHOD} !^POST$

# Forcing HTTPS
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{SERVER_PORT} 80
# Pages to Apply
RewriteCond %{REQUEST_URI} ^something_secure [OR]
RewriteCond %{REQUEST_URI} ^something_else_secure
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

# Forcing HTTP
RewriteCond %{HTTPS} =on [OR]
RewriteCond %{SERVER_PORT} 443
# Pages to Apply
RewriteCond %{REQUEST_URI} ^something_public [OR]
RewriteCond %{REQUEST_URI} ^something_else_public
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
Люк Стивенсон
источник
из любопытства, почему RewriteCond %{REQUEST_METHOD} !^POST$?
Депуло
12
Потому что параметры POST не сохраняются при перенаправлении. Вы можете опустить эту строку, если хотите убедиться, что все представления POST безопасны (любые незащищенные представления POST будут игнорироваться).
Люк Стивенсон
@Lucanos - Как написать RewriteCond, который не вызывает перенаправление на http или https при POST? Мой .htaccess вызывает HTTPS на определенных страницах, а затем - HTTP на остальных. Однако на страницах HTTPS есть формы, которые отправляются в мой веб-корень. Форма указывает URL-адрес действия как HTTPS. Однако, поскольку веб-корень не является одной из тех страниц, которые указаны для принудительной установки HTTPS, мой .htaccess затем вызывает перенаправление - это означает, что переменные POST теряются. Как предотвратить перенаправления на POST?
StackOverflowNewbie
1
@StackOverflowNewbie: строка RewriteCond %{REQUEST_METHOD} !^POST$должна предотвращать влияние этих перенаправлений на отправку POST.
Люк Стивенсон
Мне нравится эта версия PHP. Это намного лучше, поскольку он считает POST и обрабатывает лучше, если заголовки уже отправлены.
TheStoryCoder
10

Мод-переписать решение на основе:

Использование следующего кода в htaccess автоматически перенаправляет все http-запросы на https.

RewriteEngine on

RewriteCond %{HTTPS}::%{HTTP_HOST} ^off::(?:www\.)?(.+)$
RewriteRule ^ https://www.%1%{REQUEST_URI} [NE,L,R]

Это перенаправит ваши запросы не-www и www на www- версию https.

Другое решение (Apache 2.4 *)

RewriteEngine on

RewriteCond %{REQUEST_SCHEME}::%{HTTP_HOST} ^http::(?:www\.)?(.+)$
RewriteRule ^ https://www.%1%{REQUEST_URI} [NE,L,R]

Это не работает на более низких версиях apache, так как переменная% {REQUEST_SCHEME} была добавлена ​​в mod-rewrite начиная с версии 2.4.

starkeen
источник
9

Я просто хотел бы отметить, что Apache имеет худшие правила наследования при использовании нескольких файлов .htaccess на разных глубинах каталогов. Два ключевых подводных камня:

  • Только правила, содержащиеся в самом глубоком файле .htaccess, будут выполняться по умолчанию. Вы должны указать RewriteOptions InheritDownBeforeдирективу (или аналогичную), чтобы изменить это. (см. вопрос)
  • Шаблон применяется к пути к файлу относительно подкаталога, а не к верхнему каталогу, содержащему файл .htaccess с данным правилом. (см. обсуждение)

Это означает , что предлагаемое глобальное решение на Apache Wiki это не будет работать , если вы используете какие - либо другие файлы .htaccess в подкаталогах. Я написал модифицированную версию, которая делает:

RewriteEngine On
# This will enable the Rewrite capabilities

RewriteOptions InheritDownBefore
# This prevents the rule from being overrided by .htaccess files in subdirectories.

RewriteCond %{HTTPS} !=on
# This checks to make sure the connection is not already HTTPS

RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [QSA,R,L]
# This rule will redirect users from their original location, to the same location but using HTTPS.
# i.e.  http://www.example.com/foo/ to https://www.example.com/foo/
LPD
источник
0

Просто и легко, просто добавьте следующее

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Саураб Мисти
источник
Это в значительной степени то, что люди во всем Интернете говорят вам, чтобы заставить https. Однако каждый раз, когда я это делаю, весь мой сайт становится ЗАПРЕЩЕННЫМ или у вас нет разрешения на просмотр. что-то подобное ... Что я делаю не так? Я просто хочу знать, есть ли у вас какие-либо идеи, прежде чем я отправлю вопрос по этому вопросу.
Thn
У меня была похожая проблема, и мне пришлось применить правила к файлу https.conf. Смотрите мой ответ ниже.
Ристард
-1

Этот код работает для меня

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP:X-HTTPS} !1
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
Alexufo
источник
-1

Простой:

RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.example\.com)(:80)? [NC]
RewriteRule ^(.*) https://example.com/$1 [R=301,L]
order deny,allow

замените ваш URL на example.com

Сепер Норузи
источник
НЕТ! URL сайта должен быть динамическим.
Амир Саванд
-1

для принудительного использования SSL с Apache .htaccess вы можете использовать

SSLOptions +StrictRequire
SSLRequireSSL

для перенаправления вышеуказанный ответ правильный

webdesignwien
источник
-1

попробуйте этот код, он будет работать для всех версий URL, таких как

  • website.com
  • www.website.com
  • http://website.com
  • http://www.website.com

    RewriteCond %{HTTPS} off
    RewriteCond %{HTTPS_HOST} !^www.website.com$ [NC]
    RewriteRule ^(.*)$ https://www.website.com/$1 [L,R=301]
Кашиф Латиф
источник