Как я могу заставить SSL/https использовать .htaccess и mod_rewrite page specific в PHP.
Ответ 1
Для Apache вы можете использовать mod_ssl для принудительного использования SSL с помощью директивы SSLRequireSSL. Эта директива запрещает доступ, если для текущего соединения не включен 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();
}
}
Ответ 2
Я нашел решение mod_rewrite, которое хорошо работает как для проксированных, так и для непроксированных серверов. Если вы используете CloudFlare, AWS Elastic Load Balancing, Heroku, OpenShift или любое другое решение Cloud/PaaS и испытываете зацикливание перенаправления при обычном перенаправлении HTTPS, попробуйте использовать следующий фрагмент.
RewriteEngine On
# Если мы получаем перенаправленный http-запрос от прокси-сервера...
RewriteCond % { HTTP:X-Forwarded-Proto } =http [OR]
# ...или обычный старый http запрос непосредственно от клиента
RewriteCond % { HTTP:X-Forwarded-Proto } =""
RewriteCond % { HTTPS } !=on
# Перенаправление на https-версию
RewriteRule ^ https://% { HTTP_HOST } % { REQUEST_URI } [L,R=301]
Ответ 3
Решение PHP
Я заметил, что в вашем вопросе упоминается специфичность страницы для принудительного HTTPS/SSL-соединения.
function forceHTTPS() {
$httpsURL = 'https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
if( count( $_POST )>0 )
die( 'Доступ к странице должен осуществляться по HTTPS, но здесь отправлено POST-представление. Настройте форму так, чтобы она указывала на '.$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, вы можете потребовать централизованный файл, содержащий эту (и любые другие) пользовательские функции, а затем просто запустить функцию forceHTTPS().
Решение HTACCESS / mod_rewrite
Я лично не реализовывал подобное решение (я склонялся к использованию PHP-решения, как описано выше, из-за его простоты), но следующее может быть, по крайней мере, хорошим началом.
RewriteEngine on
# Проверка представления POST
RewriteCond % { REQUEST_METHOD } !^POST$
# Принудительное использование HTTPS
RewriteCond % { HTTPS } !=on [OR]
RewriteCond % { SERVER_PORT } 80
# Страницы для подачи заявки
RewriteCond % { REQUEST_URI } ^something_secure [OR]
RewriteCond % { REQUEST_URI } ^something_else_secure
RewriteRule .* https://% { SERVER_NAME } % { REQUEST_URI } [R=301,L]
# Принудительный HTTP
RewriteCond % { HTTPS } =on [OR]
RewriteCond % { SERVER_PORT } 443
# Страницы для подачи заявки
RewriteCond % { REQUEST_URI } ^что-то_другое_публичное
RewriteRule .* http://% { SERVER_NAME } % { REQUEST_URI } [R=301,L]
Ответ 4
Решение на основе Mod-rewrite. Использование следующего кода в htaccess автоматически перенаправляет все http-запросы на https.
RewriteEngine on
RewriteCond % { HTTPS } ::% { HTTP_HOST } ^off::(?:www\.)?(.+)$
RewriteRule ^ https://www.%1% { REQUEST_URI } [NE,L,R]
Это перенаправит ваши не-www и www http запросы на 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.
Ответ 5
Я хотел бы отметить, что Apache имеет наихудшие правила наследования при использовании нескольких файлов .htaccess в глубине каталога. Два основных подводных камня:
-
По умолчанию будут выполняться только правила, содержащиеся в самом глубоком файле .htaccess. Вы должны указать директиву RewriteOptions InheritDownBefore (или аналогичную), чтобы изменить это.
-
Шаблон применяется к пути к файлу относительно подкаталога, а не верхнего каталога, содержащего файл .htaccess с заданным правилом.
Это означает, что предложенное глобальное решение на Apache Wiki не работает, если вы используете любые другие файлы .htaccess в подкаталогах. Я написал модифицированную версию, которая работает:
RewriteEngine On
# Это позволит включить возможности Rewrite
RewriteOptions InheritDownBefore
# Это предотвращает переопределение правила файлами .htaccess в подкаталогах.
RewriteCond % { HTTPS } !=on
# Здесь проверяется, что соединение не является HTTPS.
RewriteRule ^ https://% { SERVER_NAME } % { REQUEST_URI } [QSA,R,L]
# Это правило перенаправит пользователей с их первоначального местоположения на то же место, но с использованием HTTPS.
# то есть http://www.example.com/foo/ to https://www.example.com/foo/