htaccess перенаправить на https: // www

309

У меня есть следующий код htaccess:

<IfModule mod_rewrite.c>

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

</IfModule>

Я хочу, чтобы мой сайт перенаправлялся по https://www.протоколу HTTPS и осуществлял принудительное использование www.субдомена, но когда я получаю доступ http://www.(без HTTPS), он не перенаправляет меня по https://wwwHTTPS.

большой Бен
источник
Должно бытьRewriteCond %{HTTPS} =off
Михаил Берковски
1
Если я сделаю это, он перенаправит на https: / / ww ww w w.
bigben
Уважаемый @bigben, вы приняли здесь неправильный ответ! Вы можете узнать, почему это неправильно в моем ответе .
Амир Фо

Ответы:

632

Чтобы сначала принудительно установить HTTPS, вы должны проверить правильную переменную среды %{HTTPS} off, но ваше правило, приведенное выше, затем добавляется, так как у www.вас есть второе правило для применения www., не используйте его в первом правиле.

RewriteEngine On
RewriteCond %{HTTPS} off
# First rewrite to HTTPS:
# Don't put www. here. If it is already there it will be included, if not
# the subsequent rule will catch it.
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Now, rewrite any request to the wrong domain to use www.
# [NC] is a case-insensitive match
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

О проксировании

При наличии некоторых форм прокси, когда клиент подключается через HTTPS к прокси, балансировщику нагрузки, приложению Passenger и т. Д., %{HTTPS}Эта переменная может никогда не возникать onи вызывать цикл перезаписи. Это происходит потому, что ваше приложение фактически получает простой HTTP-трафик, хотя клиент и прокси-сервер / балансировщик нагрузки используют HTTPS. В этих случаях проверьте X-Forwarded-Protoзаголовок вместо %{HTTPS}переменной. Этот ответ показывает соответствующий процесс

Майкл Берковски
источник
14
В некоторых случаях ваш сертификат может быть полезен только для одного домена (например, он может работать с www, но не без него). В таких случаях сначала перенаправьте на правильный домен, а затем на https, в противном случае вы получите сообщение об ошибке в вашем браузере.
Ник Бенсон
19
Когда я использовал RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]URL-адрес, такой как exaple.com/?bla=%20 стал exaple.com/?bla=%2520 , то есть знак процента был закодирован. Рассмотрите возможность использования флага NEдля предотвращения двойного кодирования:RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [NE,L,R=301]
Удар
5
это дает мне цикл перенаправления на одном сервере, работает на другом. я действительно не знаю почему
user151496
4
@ user151496 Использует ли отказавший сервер какой-либо HTTP-прокси, например, через кеш Varnish или в Passenger? Если это так, вам, возможно, придется проверить X-Forwarded-Protoзаголовок, чтобы проверить HTTPS вместо %{HTTPS}переменной. Вы не сказали, какая часть вызывает цикл, часть wwwили HTTPS, но это первое, что приходит мне в голову.
Майкл Берковски
5
Строго говоря, два приведенных выше правила находятся в неправильном порядке. Если запрос приходит http://example.com(например, HTTP и не www), то вы получите двойное перенаправление. Сначала https://example.com(первое правило), а затем https://www.example.com(второе правило). Это можно исправить, просто изменив эти два правила, так как оба правила перенаправляют на HTTPS независимо.
MrWhite
149

Ответ Михалса сработал для меня, хотя и с одной маленькой модификацией:

Проблема:

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

Решение

Сначала используйте перенаправление на www (или любой домен, на который распространяется ваш сертификат), и только после этого выполняйте перенаправление https. Это гарантирует, что ваши пользователи не столкнутся ни с какой ошибкой, потому что ваш браузер видит сертификат, который не покрывает текущий URL.

#First rewrite any request to the wrong domain to use the correct one (here www.)
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

#Now, rewrite to HTTPS:
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Larzan
источник
5
+1, потому что это лучший вариант для этого сценария, но учтите, что это не предотвратит возникновение той же проблемы, если клиент получает доступ https://example.com, но, по моему мнению, это наименее вероятный формат, который будет вводиться пользователем. (Принятый ответ также будет иметь ту же проблему)
Джошуа Гуссен
@ Ларзан: Это неправильно. Исключение сертификации происходит только потому, что вы делаете 2 реальных перенаправления. Заменить "[L, R = 301]" на "[R = 301]". Эти правила не отменяются. L = LAST
определено
Если вам нужно обрабатывать, https://не wwwимея при этом только сертификата www, просто добавьте это правило к решению: RewriteCond %{HTTP_HOST} !^www\. RewriteCond %{HTTPS} on RewriteRule ^(.*)$ http://www.%{HTTP_HOST}%{REQUEST_URI}[L,R=301] оно просто возвращается к тому, httpкогда пытается подключиться, https://example.comчтобы избежать ошибки сертификата.
Эрик Бурел
1
В любом случае эти два правила следует поменять (как вы это сделали), чтобы избежать двойного перенаправления при запросе http://example.com(т.
Е.
@EricBurel Вы не можете избежать ошибки сертификата в этом случае - рукопожатие SSL происходит до того, как исполняется ваш код (что, в первую очередь, и есть смысл SSL). Если бы ваш редирект был выполнен до того, как браузер подтвердил ошибку, это означало бы, что запрос уже был сделан по небезопасному соединению - что будет фундаментальным сбоем в модели SSL.
MrWhite
99

Если вы используете CloudFlare или аналогичный CDN, вы получите ошибку бесконечного цикла с решениями% {HTTPS}, представленными здесь. Если вы пользователь CloudFlare, вам нужно использовать это:

RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Андрей
источник
2
Обратите внимание, что текущие рекомендации на сайте поддержки Cloudflare немного отличаются: support.cloudflare.com/hc/en-us/articles/…
ColinMcDermott
1
Согласитесь с @ h0mayun, совет Cloudflare дает результаты в цикле перенаправления, тогда как этот код здесь работает отлично - спасибо!
Hobailey
2
Я запускаю angularjs на ec2. Решения, использующие RewriteCond% {HTTPS}! = On, дают мне бесконечное перенаправление (не совсем понятно, почему). Это решение с X-Forwarded-Proto, кажется, делает свое дело. Спасибо!
Марк Уоткинс
3
Я изменил =httpв !=httpsнаших условиях. X-Forwarded-Protoзаголовок не был объявлен, если http, так !=httpsже как и хитрость
Джонатан Элмор
Спасибо за это понимание! Я часами пытался понять, почему {HTTPS}не работает. Я попробовал {ENV:HTTPS}и даже {SERVER_PORT} 443, но в конце концов это было потому, что мне нужно было проверить наличие пользовательских заголовков HTTP-запросов Cloudflare.
Camslice
56

ПЛОХОЕ РЕШЕНИЕ И ПОЧЕМУ!

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

RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule .* https://www.example.com%{REQUEST_URI} [L,R=301]

Браузер переходит к:

http://example.com

Затем перенаправляет на:

https://example.com

Затем перенаправляет на:

https://www.example.com

Это слишком большая просьба к серверу.

У большинства ответов, даже принятых один, есть эта проблема.


ЛУЧШЕЕ РЕШЕНИЕ И ОТВЕТ

Этот код имеет [OR]условие для предотвращения двойных изменений в URL!

RewriteEngine on
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule (.*) https://www.example.com%{REQUEST_URI} [R=301,L]
Амир Фо
источник
3
"ПЛОХОЕ РЕШЕНИЕ И ПОЧЕМУ!" - Эти правила просто в неправильном порядке. Отмените эти два правила, и это будет правильно - вы получите только одно перенаправление, а не два.
MrWhite,
4
Да, приведенный код приводит к двум переадресациям - я не оспариваю это - все, что я говорю, это то, что вам просто нужно отменить эти правила для решения этой проблемы, никаких других изменений не требуется. («Принятый» ответ действительно неверен - кажется, это то, на что вы ссылаетесь - директивы в неправильном порядке.)
MrWhite,
1
да @AmirForsati прав. это перенаправление дважды, и это должен быть принятый ответ.
Закир Хуссейн
4
Вы можете использовать это, если хотите сохранить переменную domainname:RewriteEngine On RewriteCond %{HTTPS} off RewriteCond %{HTTP_HOST} !^www\. [NC] RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301] RewriteCond %{HTTPS} off RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
I.devries
Это перенаправляет меня wp-content/cache/page_enhanced/и так далее. Как я могу это исправить? Изменить: Похоже, мне нужно положить его наверху .htaccess. Спасибо за сценарий :)
Джакомо
35

Это лучший способ, который я нашел для прокси, а не пользователей прокси

RewriteEngine On

### START WWW & HTTPS

# ensure www.
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

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

### END WWW & HTTPS
llioor
источник
2
Правильно Это лучший способ, который я нашел для прокси-серверов, а не для прокси-пользователей +1
Deep 3015
1
Это лучший, так как он решает несколько переадресаций 301
Niraj Chauhan
1
лучшее решение когда-либо.
SM Jobayer Alam
1
Отличный ответ. Это единственный, который работал на меня. Работает, если вы находитесь за Cloudflare (хотя у меня не настроены правила для страниц в Cloudflare).
Джейсонко
Единственное решение, которое работает во всех моих случаях. Но что, если я захочу сделать де-опозит и удалить все "www".
ФедеКрум
27

Есть много решений там. Вот ссылка на Apache Wiki, которая непосредственно занимается этой проблемой.

http://wiki.apache.org/httpd/RewriteHTTPToHTTPS

RewriteEngine On
# This will enable the Rewrite capabilities

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

RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [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/
# The leading slash is made optional so that this will work either in httpd.conf
# or .htaccess context
Vynz
источник
Я нашел, изменив условие перезаписи с RewriteCond %{HTTPS} off на RewriteCond %{HTTPS} !=onто, что перенаправление всегда будет происходить, мне кажется, это лучший ответ.
Сэмюэль Хоксби-Робинсон
Это решение должно быть принято как правильный ответ! У меня тоже сработало!
AndrewShmig
11

Чтобы перенаправить http: // или https: // на https: // www, вы можете использовать следующее правило для всех версий apache:

RewriteEngine on

RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ https://www.example.com%{REQUEST_URI} [NE,L,R]

Apache 2.4

RewriteEngine on

RewriteCond %{REQUEST_SCHEME} http [OR]
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ https://www.example.com%{REQUEST_URI} [NE,L,R]

Обратите внимание, что переменная% {REQUEST_SCHEME} доступна для использования начиная с Apache 2.4 .

starkeen
источник
1
Проблема !: Если HTTP_HOST уже содержит www. но схема не HTTPS, тогда вы в конечном итоге с www.www. в вашем хосте.
Jpsy
@ Jpsy, ты прав. Я обновил пункт назначения Redirect. Спасибо за ваш вклад.
Старкин
1
Это почти то, что я искал, но я хочу оставить домен общим, как в других примерах. Является ли это возможным?
Cronoklee
8

Если вы находитесь на CloudFlare, убедитесь, что вы используете что-то вроде этого.

# BEGIN SSL Redirect
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>
# END SSL Redirect

Это избавит вас от цикла перенаправления и безопасно перенаправит ваш сайт на SSL.

PS Это хорошая идея, если проверить mod_rewrite.c!

Ахмад Авайс
источник
он не перенаправляет https: // theurlwithoutwww.com на https: // www.
родительские дроиды
На самом деле это единственное рабочее решение, если у вас есть какие-то директивы add www. Другие решения дают мне «много перенаправлений».
Daniel.P.
3
RewriteEngine On 
RewriteCond %{SERVER_PORT} 80 
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R]
Анастасия Ермолик
источник
2
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]

Примечания: убедитесь, что вы сделали следующие шаги

  1. sudo a2enmod переписать
  2. перезапуск службы sudo apache2
  3. Добавьте следующее в ваш vhost-файл, расположенный по адресу /etc/apache2/sites-available/000-default.conf
<Directory /var/www/html>
  Options Indexes FollowSymLinks MultiViews
  AllowOverride All
  Order allow,deny
  allow from all
  Require all granted
</Directory>

Теперь ваш .htaccess будет работать, и ваш сайт будет перенаправлен с http: // на https: // www.

Кундан Рой
источник
1

По аналогии с решением Амира Форсати htaccess перенаправить на https: // www, но для переменного доменного имени я предлагаю:

RewriteEngine on
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} ^(www\.)?(.+)$ [NC]
RewriteRule ^ https://www.%2%{REQUEST_URI} [R=301,L]
Бернхард Боденсторфер
источник
0

Установите в своем файле .htaccess

RewriteEngine On
RewriteCond %{HTTP_HOST} !^www.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Адам Козловский
источник
-2

Я пытаюсь сначала ответить, и это не работает ... Эта работа:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

RewriteCond %{ENV:HTTPS} !=on
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R,L]

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress
Jackssn
источник