Автоматический редирект на HTTPS, если браузер его поддерживает

Список разделов phpBBex 1.x (поддерживается) Мастерская 1.x

Описание: Только готовые решения! Статьи, заметки, моды и другие полезности для phpBBex 1.x и phpBB 3.0.x.
Модератор: Поддержка

Сообщение #1 VEG » 15.11.2020, 17:50

В современном вебе стоит использовать HTTPS, и желательно настроить автоматический редирект на HTTPS, если у пользователя достаточно свежий браузер. Предлагаю следующую конфигурацию для Apache, которую нужно поместить в самое начало файла .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, в зависимости от свежести браузера пользователя).
VEG M
Автор темы, Администратор
Аватара
Откуда: Finland
Репутация: 1668
С нами: 12 лет 7 месяцев

Сообщение #2 Sumanai » 17.11.2020, 19:41

VEG:Apache
А ты старовер ))
Sumanai M
Аватара
Репутация: 1677
С нами: 11 лет 9 месяцев

Сообщение #3 VEG » 17.11.2020, 21:58

Работает — не трожь =)
VEG M
Автор темы, Администратор
Аватара
Откуда: Finland
Репутация: 1668
С нами: 12 лет 7 месяцев

Сообщение #4 VEG » 19.11.2020, 18:05

Недавно было в новостях, что Let's Encrypt переходит на собственный корневой сертификат "ISRG Root X1" (действителен до 2035 года), поэтому их сертификаты перестанут приниматься на необновлённых системах, которые ничего не знают про "ISRG Root X1". Под ударом Android до версии 7.1.1, необновлённые Windows до 2018 года. Обновил приведённый выше код с учётом этого, чтобы в старом ПО отключить автоматический редирект на HTTPS по чёрному списку User-Agent устаревших ОС и браузеров.

Код: Выделить всё
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.
# ----------------------------------------------------------------------------------------------------------------------

# Let's Encrypt "DST Root CA X3" 2021-: Firefox 2+, Windows XP SP3+, Android 2.3.6+, iOS 3.1+, Safari 4+, MacOS 10.4+.
# Let's Encrypt "ISRG Root X1"   2021+: Firefox 50+, Windows 7+ (2018/07/31), Android 7.1.1+ (2017), iOS 10+ (2017).
# Windows XP: Firefox 52-, Chrome 49-. Chrome 70 was released 2018/10/16 (older version may be on too old Windows).
# 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).

# Allow UIR if Upgrade-Insecure-Requests is in the request headers.
RewriteRule ^ - [E=PERMIT_UIR:0]
RewriteCond %{HTTP:Upgrade-Insecure-Requests} ^1$
RewriteRule ^ - [E=PERMIT_UIR:1]

# Allow STS if UIR is allowed, and browser and OS are not too old (and probably support Let's Encrypt).
RewriteRule ^ - [E=PERMIT_STS:0]
RewriteCond %{ENV:PERMIT_UIR} ^1$
RewriteCond %{HTTP_USER_AGENT} !Android\s([1-6]\.|7\.0|7\.1\.0)
RewriteCond %{HTTP_USER_AGENT} !Windows\sNT\s(5\.|6\.0)
RewriteCond %{HTTP_USER_AGENT} !Mac\sOS\sX\s10_1[0-2]
RewriteCond %{HTTP_USER_AGENT} !(iPhone|iPad);\sCPU\s(iPhone\s)?OS\s[1-9]_
RewriteCond %{HTTP_USER_AGENT} !Firefox\/[1-4]?[0-9]\.
RewriteCond %{HTTP_USER_AGENT} !Chrome\/[1-6]?[0-9]\.
RewriteRule ^ - [E=PERMIT_STS:1]

# Force HTTPS if STS is allowed and forcessl cookie is not 0.
RewriteRule ^ - [E=USE_SCHEME:%{ENV:REQ_SCHEME}]
RewriteCond %{ENV:PERMIT_STS} ^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 STS isn't allowed, forcessl cookie isn't set, and current scheme is HTTPS.
# RewriteCond %{ENV:REQ_SCHEME} ^https$
# RewriteCond %{ENV:PERMIT_STS} !^1$
# RewriteCond %{HTTP_COOKIE} !(?:^|;)\s*forcessl=[-01]\s*(?:;|$)
# RewriteCond %{ENV:SET_FORCESSL_COOKIE} !^[-01]$
# RewriteRule ^ - [E=SET_FORCESSL_COOKIE:1]

# Canonical prefix.
RewriteRule ^ - [E=URI_PREFIX:%{ENV:USE_SCHEME}://%{HTTP_HOST}]

# Decide if we want to send STS and UIR headers. Never send them when current request is HTTP.
RewriteCond %{ENV:REQ_SCHEME} ^https$
RewriteRule ^ - [E=SET_FORCESTS_HEADER:0,E=SET_FORCEUIR_HEADER:0]
RewriteCond %{ENV:REQ_SCHEME} ^https$
RewriteCond %{ENV:USE_SCHEME} ^https$
RewriteRule ^ - [E=SET_FORCESTS_HEADER:%{ENV:PERMIT_STS},E=SET_FORCEUIR_HEADER:%{ENV:PERMIT_UIR}]

# Try to fix stupid adding of the "REDIRECT_" prefix to environment variable names on URL rewrite.
SetEnvIf REDIRECT_PERMIT_UIR            (.+) PERMIT_UIR=$1
SetEnvIf REDIRECT_PERMIT_STS            (.+) PERMIT_STS=$1
SetEnvIf REDIRECT_REQ_SCHEME            (.+) REQ_SCHEME=$1
SetEnvIf REDIRECT_USE_SCHEME            (.+) USE_SCHEME=$1
SetEnvIf REDIRECT_URI_PREFIX            (.+) URI_PREFIX=$1
SetEnvIf REDIRECT_SET_FORCESSL_COOKIE   (.+) SET_FORCESSL_COOKIE=$1
SetEnvIf REDIRECT_SET_FORCESTS_HEADER   (.+) SET_FORCESTS_HEADER=$1
SetEnvIf REDIRECT_SET_FORCEUIR_HEADER   (.+) SET_FORCEUIR_HEADER=$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'"

# Send the STS and UIR headers if required. 2592000 seconds = 30 days.
Header always set Strict-Transport-Security "max-age=2592000"           "expr= '%{ENV:SET_FORCESTS_HEADER}' == '1'"
Header always set Strict-Transport-Security "max-age=0"                 "expr= '%{ENV:SET_FORCESTS_HEADER}' == '0'"
Header always set Content-Security-Policy "upgrade-insecure-requests"   "expr= '%{ENV:SET_FORCEUIR_HEADER}' == '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]

# ----------------------------------------------------------------------------------------------------------------------

Firefox использует собственное хранилище корневых сертификатов, поэтому в Firefox 50+ даже на необновлённой версии Windows всё будет работать. Такую же фичу хотят сделать в Chrome. Когда это будет сделано, я расширю список версий Chrome где отключен автоматический редирект до той, где начнёт использоваться собственное хранилище, где будет и "ISRG Root X1".
VEG M
Автор темы, Администратор
Аватара
Откуда: Finland
Репутация: 1668
С нами: 12 лет 7 месяцев

Сообщение #5 VEG » 02.02.2022, 18:36

Для совместимости старых Android с версией ниже 7.1.1, Let's Encrypt сейчас использует корневой сертификат "DST Root CA X3", который истекает в сентябре 2024. Но это больше не проблема, так как Chrome 98+, как и Firefox, теперь также использует собственное хранилище корневых сертификатов, где имеются "ISRG Root X1" (до 2035 года) и "ISRG Root X2" (до 2040 года). Так что в свежем браузере (Firefox или Chrome) на необновлённой ОС всё должно продолжать работать нормально даже после истечения "DST Root CA X3".

Chrome 98 поддерживает Android 6 и новее. Так что Android 4 и 5 останутся за бортом. Но они и сейчас практически не встречаются (на одном моём популярном сайте, ориентированном на пользователей смартфонов, их всего 1.55% в сумме), а к сентябрю 2024 их наверняка останется ещё в раза три меньше.
VEG M
Автор темы, Администратор
Аватара
Откуда: Finland
Репутация: 1668
С нами: 12 лет 7 месяцев

Сообщение #6 Merz » 03.02.2022, 22:28

VEG:популярном сайте
Что за сайт?
Merz M
Аватара
Репутация: 33
С нами: 10 лет 3 месяца

Сообщение #7 VEG » 05.02.2022, 11:54

Я имел в виду radar.veg.by. Впрочем, его популярность весьма относительна. Просто им пользуется в разы больше людей, чем всеми остальными моими сайтами вместе взятыми. О действительно большой популярности речи не идёт, конечно.
VEG M
Автор темы, Администратор
Аватара
Откуда: Finland
Репутация: 1668
С нами: 12 лет 7 месяцев

Сообщение #8 VEG » 13.01.2024, 17:06

Третья версия конфига. Уточнён детект гарантированной поддержки сертификатов Let's Encrypt.

Код: Выделить всё
RewriteEngine On
RewriteBase /

# ----------------------------------------------------------------------------------------------------------------------
# Force HTTPS and canonical host if required.
# ----------------------------------------------------------------------------------------------------------------------

# Set canonical host.
RewriteCond %{HTTP_HOST} ^(?:www\.)+(.+) [NC]
RewriteRule ^ - [E=FORCE_HOST:%1]

# Detect current scheme. REQUEST_SCHEME is not reliable since Apache might 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]

# Force canonical host. We should do it before we try to set any cookies or any other redirects.
RewriteCond expr "%{ENV:FORCE_HOST} != '' && tolower(%{HTTP_HOST}) != tolower(%{ENV:FORCE_HOST})"
RewriteRule ^/?(.*)$ %{ENV:REQ_SCHEME}://%{ENV:FORCE_HOST}/$1 [NE,R=301,END]

# Allow UIR if Upgrade-Insecure-Requests is in the request headers.
# UIR support: IE18+ (2018), Firefox 48+ (2016), Chrome 44+ (2015), Safari 10.1+ (2017, MacOS 10.10+).
RewriteRule ^ - [E=PERMIT_UIR:0]
RewriteCond %{HTTP:Upgrade-Insecure-Requests} ^1$
RewriteRule ^ - [E=PERMIT_UIR:1]

# Allow Strict-Transport-Security if UIR is supported, and browser trusts Let's Encrypt's "ISRG Root X1":
# - OS: Windows 7+ (2018/07/31), Android 7.1.1+ (2017), iOS 10+ (2017), MacOS 10.12.1+ (2016).
# - Browsers: Firefox 50+ (2016), Chrome 108+ (2022, Windows/MacOS) 114+ (2023, Linux/ChromeOS) 115+ (2023, Android).
# STS support: IE11+ (2015), Firefox 4+ (2011), Chrome 4+ (2010), Safari 7+ (2013), Android 4.4+ (2013).
# Windows XP: Firefox 52- (2017), Chrome 49- (2016), IE8. Windows 7-8.1: Firefox 115- (2023), Chrome 109- (2023), IE11.
RewriteRule ^ - [E=PERMIT_STS:0]
RewriteCond %{ENV:PERMIT_UIR} ^1$
RewriteCond %{HTTP_USER_AGENT} !Android\s([1-6]\.|7\.0|7\.1\.0)
RewriteCond %{HTTP_USER_AGENT} !Windows\sNT\s(5\.|6\.0)
RewriteCond %{HTTP_USER_AGENT} !Mac\sOS\sX\s10[_.]1[0-2]
RewriteCond %{HTTP_USER_AGENT} !(iPhone|iPad);\sCPU\s(iPhone\s)?OS\s[1-9][_.]
RewriteCond %{HTTP_USER_AGENT} !Firefox\/[1-4]?[0-9]\.
RewriteCond %{HTTP_USER_AGENT} !Chrome\/([1-9]?[0-9]|10[0-7])\.
RewriteCond %{HTTP_USER_AGENT} !Android.+Chrome\/(10[8-9]|11[0-4])\.
RewriteRule ^ - [E=PERMIT_STS:1]

# Force HTTPS if STS is allowed and forcessl cookie is not 0.
RewriteRule ^ - [E=URL_SCHEME:%{ENV:REQ_SCHEME}]
RewriteCond %{ENV:PERMIT_STS} ^1$
RewriteCond %{HTTP_COOKIE} !(?:^|;)\s*forcessl=0\s*(?:;|$)
RewriteRule ^ - [E=URL_SCHEME:https]

# Use HTTPS if forcessl cookie is 1.
RewriteCond %{HTTP_COOKIE}  (?:^|;)\s*forcessl=1\s*(?:;|$)
RewriteRule ^ - [E=URL_SCHEME:https]

# Set or remove the forcessl cookie depending on the forcessl URL parameter.
RewriteCond %{QUERY_STRING} (?:^|&)forcessl=-(?:&|$)
RewriteRule ^ - [E=SET_FORCESSL_COOKIE:-,E=URL_SCHEME:http]
RewriteCond %{QUERY_STRING} (?:^|&)forcessl=0(?:&|$)
RewriteRule ^ - [E=SET_FORCESSL_COOKIE:0,E=URL_SCHEME:http]
RewriteCond %{QUERY_STRING} (?:^|&)forcessl=1(?:&|$)
RewriteRule ^ - [E=SET_FORCESSL_COOKIE:1,E=URL_SCHEME:https]

# Set forcessl=1 if STS isn't allowed, forcessl cookie isn't set, and current scheme is HTTPS.
# RewriteCond %{ENV:REQ_SCHEME} ^https$
# RewriteCond %{ENV:PERMIT_STS} !^1$
# RewriteCond %{HTTP_COOKIE} !(?:^|;)\s*forcessl=[-01]\s*(?:;|$)
# RewriteCond %{ENV:SET_FORCESSL_COOKIE} !^[-01]$
# RewriteRule ^ - [E=SET_FORCESSL_COOKIE:1]

# Canonical prefix.
RewriteRule ^ - [E=URL_PREFIX:%{ENV:URL_SCHEME}://%{HTTP_HOST}]

# Decide if we want to send STS and UIR headers. Never send them when current request is HTTP.
RewriteCond %{ENV:REQ_SCHEME} ^https$
RewriteRule ^ - [E=SET_FORCESTS_HEADER:0,E=SET_FORCEUIR_HEADER:0]
RewriteCond %{ENV:REQ_SCHEME} ^https$
RewriteCond %{ENV:URL_SCHEME} ^https$
RewriteRule ^ - [E=SET_FORCESTS_HEADER:%{ENV:PERMIT_STS},E=SET_FORCEUIR_HEADER:%{ENV:PERMIT_UIR}]

# Try to fix stupid adding of the "REDIRECT_" prefix to environment variable names on URL rewrite.
SetEnvIf REDIRECT_PERMIT_UIR            (.+) PERMIT_UIR=$1
SetEnvIf REDIRECT_PERMIT_STS            (.+) PERMIT_STS=$1
SetEnvIf REDIRECT_REQ_SCHEME            (.+) REQ_SCHEME=$1
SetEnvIf REDIRECT_URL_SCHEME            (.+) URL_SCHEME=$1
SetEnvIf REDIRECT_URL_PREFIX            (.+) URL_PREFIX=$1
SetEnvIf REDIRECT_SET_FORCESSL_COOKIE   (.+) SET_FORCESSL_COOKIE=$1
SetEnvIf REDIRECT_SET_FORCESTS_HEADER   (.+) SET_FORCESTS_HEADER=$1
SetEnvIf REDIRECT_SET_FORCEUIR_HEADER   (.+) SET_FORCEUIR_HEADER=$1

# Send cookies in modern format with Max-Age. In old browsers like IE11 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=34560000"     "expr= '%{ENV:SET_FORCESSL_COOKIE}' == '0'"
Header always add Set-Cookie "forcessl=1; Path=/; Max-Age=34560000"     "expr= '%{ENV:SET_FORCESSL_COOKIE}' == '1'"

# Send the STS and UIR headers if required. 2592000 seconds = 30 days.
Header always set Strict-Transport-Security "max-age=2592000"           "expr= '%{ENV:SET_FORCESTS_HEADER}' == '1'"
Header always set Strict-Transport-Security "max-age=0"                 "expr= '%{ENV:SET_FORCESTS_HEADER}' == '0'"
Header always set Content-Security-Policy "upgrade-insecure-requests"   "expr= '%{ENV:SET_FORCEUIR_HEADER}' == '1'"

# Remove the forcessl URL parameter.
RewriteCond %{QUERY_STRING} ^(.*&|)forcessl=[-01](?:&(.*)|)$
RewriteRule ^/?(.*)$ %{ENV:URL_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:URL_SCHEME} !^(.+):\1$
RewriteRule ^/?(.*)$ %{ENV:URL_PREFIX}/$1 [NE,R=302,END]

# ----------------------------------------------------------------------------------------------------------------------

В самом начале в переменную FORCE_HOST заносится желаемый хост (куда попутно будет сделан авторедирект при необходимости) в виде текущего хоста без WWW. Для принудительного добавления WWW вместо удаления, используйте такой вариант:

Код: Выделить всё
RewriteCond %{HTTP_HOST} ^(?:www\.)+(.+) [NC]
RewriteRule ^ - [E=FORCE_HOST:www.%1]

Если у вас несколько разных доменов и один основной, эти строки можно заменить на установку фиксированного желаемого хоста:

Код: Выделить всё
RewriteRule ^ - [E=FORCE_HOST:phpbbex.com]

Если вам нужно добавить ещё какие-то редиректы уже внутри сайта, то лучше всего их размещать после приведённого выше кода. В редиректах можете использовать переменную %{ENV:URL_PREFIX} вместо явного указания протокола и хоста (она содержит строку вида https://example.com), или переменную %{ENV:URL_SCHEME} в качестве предпочитаемого протокола (там будет либо http, либо https).
VEG M
Автор темы, Администратор
Аватара
Откуда: Finland
Репутация: 1668
С нами: 12 лет 7 месяцев


Вернуться в Мастерская 1.x