.htaccess
в корне вашего сайта. Требуется Apache 2.4+, а также модули mod_rewrite, mod_headers и mod_setenvif (если приведённый ниже конфиг не работает, проверьте что эти модули включены).- Код: Выделить всё
RewriteEngine On
RewriteBase /
# ----------------------------------------------------------------------------------------------------------------------
# Detect current scheme. REQUEST_SCHEME is not reliable since Apache may be behind Nginx.
# ----------------------------------------------------------------------------------------------------------------------
RewriteRule ^ - [E=REQ_SCHEME:http]
RewriteCond %{HTTPS} ^on$ [NC,OR]
RewriteCond %{HTTP:X-Forwarded-Proto} https [NC,NV]
RewriteRule ^ - [E=REQ_SCHEME:https]
# ----------------------------------------------------------------------------------------------------------------------
# No www. We should do it before we try to set any cookies or any other redirects.
# ----------------------------------------------------------------------------------------------------------------------
RewriteCond %{HTTP_HOST} ^www\.(.*) [NC]
RewriteRule ^/?(.*)$ %{ENV:REQ_SCHEME}://%1/$1 [NE,R=301,END]
# ----------------------------------------------------------------------------------------------------------------------
# Force HTTPS if required.
# ----------------------------------------------------------------------------------------------------------------------
# Force HTTPS if Upgrade-Insecure-Requests is supported. Let's Encrypt is definitely supported in this case.
# Let's Encrypt is supported: Firefox 2+, Chrome 1+, Windows XP SP3+, Android OS v2.3.6+.
# Upgrade-Insecure-Requests: IE18+ (2018), Firefox 48+ (2016), Chrome 44+ (2015), Safari 10.1+ (2017).
# Strict-Transport-Security: IE11+ (2015), Firefox 4+ (2011), Chrome 4+ (2010), Safari 7+ (2013), Android 4.4+ (2013).
RewriteRule ^ - [E=USE_SCHEME:%{ENV:REQ_SCHEME}]
# Use HTTPS if UIR is supported and forcessl cookie is not 0.
RewriteCond %{HTTP:Upgrade-Insecure-Requests} ^1$
RewriteCond %{HTTP_COOKIE} !(?:^|;)\s*forcessl=0\s*(?:;|$)
RewriteRule ^ - [E=USE_SCHEME:https]
# Use HTTPS if forcessl cookie is 1.
RewriteCond %{HTTP_COOKIE} (?:^|;)\s*forcessl=1\s*(?:;|$)
RewriteRule ^ - [E=USE_SCHEME:https]
# Set or remove the forcessl cookie depending on the forcessl URL parameter.
RewriteCond %{QUERY_STRING} (?:^|&)forcessl=-(?:&|$)
RewriteRule ^ - [E=SET_FORCESSL_COOKIE:-,E=USE_SCHEME:http]
RewriteCond %{QUERY_STRING} (?:^|&)forcessl=0(?:&|$)
RewriteRule ^ - [E=SET_FORCESSL_COOKIE:0,E=USE_SCHEME:http]
RewriteCond %{QUERY_STRING} (?:^|&)forcessl=1(?:&|$)
RewriteRule ^ - [E=SET_FORCESSL_COOKIE:1,E=USE_SCHEME:https]
# Set forcessl=1 if Upgrade-Insecure-Requests isn't supported, forcessl cookie isn't set, and current scheme is HTTPS.
# RewriteCond %{ENV:REQ_SCHEME} ^https$
# RewriteCond %{HTTP:Upgrade-Insecure-Requests} !^1$
# RewriteCond %{HTTP_COOKIE} !(?:^|;)\s*forcessl=[-01]\s*(?:;|$)
# RewriteCond %{ENV:SET_FORCESSL_COOKIE} !^[-01]$
# RewriteRule ^ - [E=SET_FORCESSL_COOKIE:1]
# Decide if we want to enable STS.
RewriteCond %{ENV:REQ_SCHEME} ^https$
RewriteRule ^ - [E=SET_FORCESTS_HEADER:0]
RewriteCond %{ENV:REQ_SCHEME} ^https$
RewriteCond %{ENV:USE_SCHEME} ^https$
RewriteCond %{HTTP:Upgrade-Insecure-Requests} ^1$
RewriteCond %{HTTP_COOKIE} !(?:^|;)\s*forcessl=0\s*(?:;|$)
RewriteCond %{ENV:SET_FORCESSL_COOKIE} !^[-0]$
RewriteRule ^ - [E=SET_FORCESTS_HEADER:1]
# Try to fix stupid adding of the "REDIRECT_" prefix to environment variable names on URL rewrite.
SetEnvIf REDIRECT_USE_SCHEME (.+) USE_SCHEME=$1
SetEnvIf REDIRECT_REQ_SCHEME (.+) REQ_SCHEME=$1
SetEnvIf REDIRECT_SET_FORCESTS_HEADER (.+) SET_FORCESTS_HEADER=$1
SetEnvIf REDIRECT_SET_FORCESSL_COOKIE (.+) SET_FORCESSL_COOKIE=$1
# Send cookies in modern format with max-age (IE8+). In IE6-IE7 they will be stored until the browser is closed.
# According to RFC 6265, "host-only" cookie (which won't be sent to subdomains) shouldn't have "domain=" attribute.
Header always add Set-Cookie "forcessl=; path=/; max-age=-1" "expr= '%{ENV:SET_FORCESSL_COOKIE}' == '-'"
Header always add Set-Cookie "forcessl=0; path=/; max-age=126230400" "expr= '%{ENV:SET_FORCESSL_COOKIE}' == '0'"
Header always add Set-Cookie "forcessl=1; path=/; max-age=126230400" "expr= '%{ENV:SET_FORCESSL_COOKIE}' == '1'"
# Set the STS and UIR headers if required.
Header always set Strict-Transport-Security "max-age=2592000" "expr= '%{ENV:SET_FORCESTS_HEADER}' == '1'"
Header always set Content-Security-Policy "upgrade-insecure-requests" "expr= '%{ENV:SET_FORCESTS_HEADER}' == '1'"
Header always set Strict-Transport-Security "max-age=0" "expr= '%{ENV:SET_FORCESTS_HEADER}' == '0'"
# Canonical prefix.
RewriteRule ^ - [E=URI_PREFIX:%{ENV:USE_SCHEME}://%{HTTP_HOST}]
SetEnvIf REDIRECT_URI_PREFIX (.+) URI_PREFIX=$1
# Remove the forcessl URL parameter.
RewriteCond %{QUERY_STRING} ^(.*&|)forcessl=[-01](?:&(.*)|)$
RewriteRule ^/?(.*)$ %{ENV:URI_PREFIX}/$1?%1%2 [NE,R=302,END]
# Redirect to HTTPS or HTTP if desired scheme is different from used in this request.
RewriteCond %{ENV:REQ_SCHEME}:%{ENV:USE_SCHEME} !^(.+):\1$
RewriteRule ^/?(.*)$ %{ENV:URI_PREFIX}/$1 [NE,R=302,END]
# ----------------------------------------------------------------------------------------------------------------------
Фишки этого конфига:
- Автоматическое удаление www из хоста (если нужно, можете заменить на другой вариант установки каноничного хоста).
- Если сайт открыт через HTTPS, то автоматически настраивается
Upgrade-Insecure-Requests
(все ресурсы, ссылки на которые указаны через http, будут всё равно загружены через https) иStrict-Transport-Security
(браузер всегда будет открывать сайт по HTTPS). - Если браузер слишком старый и не поддерживает Upgrade-Insecure-Requests, то редирект на HTTPS не производится, сайт продолжает работать по HTTP.
- Пользователь может установить принудительный редирект на HTTPS (
forcessl=1
), принудительно отключить редирект (forcessl=0
), или вернуть автоматический режим (forcessl=-
), передав любой странице по любому протоколу параметрforcessl
(выбор запоминается в cookies).
Если вам надо настроить редирект с разных хостов на один каноничный — делайте это на месте удаления www. Если добавляете ещё какие-то редиректы уже внутри сайта, то лучше их размещать после приведённого выше кода. В редиректах можете использовать переменную
%{ENV:URI_PREFIX}
вместо явного указания протокола и хоста (он содержит строку вида https://example.com
), или переменную %{ENV:USE_SCHEME}
в качестве предпочитаемого протокола (там будет либо http
, либо https
, в зависимости от свежести браузера пользователя).