htaccess przekierowuje na https: // www

309

Mam następujący kod 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>

Chcę, aby moja witryna została przekierowana za https://www.pomocą HTTPS i wymusiła www.poddomenę, ale kiedy uzyskuję dostęp http://www.(bez HTTPS), nie przekierowuje mnie do niej za https://wwwpomocą HTTPS.

bigben
źródło
Powinien byćRewriteCond %{HTTPS} =off
Michael Berkowski,
1
Jeśli to zrobię, przekieruje do https: / / ww ww w w.
bigben
Drogi @bigben, tutaj przyjąłeś złą odpowiedź! możesz dowiedzieć się, dlaczego jest to źle w mojej odpowiedzi .
Amir Fo

Odpowiedzi:

632

Aby najpierw wymusić HTTPS, musisz sprawdzić poprawną zmienną środowiskową %{HTTPS} off, ale twoja reguła powyżej poprzedza: www.Ponieważ masz drugą regułę do wymuszenia www., nie używaj jej w pierwszej regule.

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]

O pośrednictwie

W przypadku niektórych form proxy, w których klient łączy się za pośrednictwem HTTPS z serwerem proxy, modułem równoważenia obciążenia, aplikacją pasażera itp., %{HTTPS}Zmienna może nigdy nie być onprzyczyną pętli przepisywania. Wynika to z faktu, że aplikacja faktycznie odbiera zwykły ruch HTTP, mimo że klient i serwer proxy / moduł równoważenia obciążenia używają protokołu HTTPS. W takich przypadkach sprawdź X-Forwarded-Protonagłówek zamiast %{HTTPS}zmiennej. Ta odpowiedź pokazuje odpowiedni proces

Michał Berkowski
źródło
14
W niektórych przypadkach twój certyfikat może być odpowiedni tylko dla jednej domeny (może współpracować z www, ale nie bez, na przykład). W takich przypadkach najpierw przekieruj do właściwej domeny, a następnie do https, w przeciwnym razie w przeglądarce pojawi się komunikat o błędzie certyfikatu.
Nick Benson
19
Kiedy użyłem RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]adresu URL takiego jak exaple.com/?bla=%20 stał się exaple.com/?bla=%2520 , tzn. Znak procentu został zakodowany. Rozważ użycie flagi, NEaby zapobiec podwójnemu kodowaniu:RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [NE,L,R=301]
Pokonaj
5
daje mi to pętlę przekierowania na jednym serwerze, działa na drugim. Naprawdę nie wiem dlaczego
15.01.2016
4
@ user151496 Czy serwer, który uległ awarii, używa jakiegokolwiek proxy proxy, na przykład przechodząc przez pamięć podręczną Varnish lub do Passenger? Jeśli tak, może być konieczne sprawdzenie X-Forwarded-Protonagłówka w celu weryfikacji HTTPS zamiast %{HTTPS}zmiennej. Nie powiedziałeś, która część powoduje pętlę, wwwczy część HTTPS, ale to pierwsza rzecz, która przychodzi mi na myśl.
Michael Berkowski
5
Ściśle mówiąc, dwie powyższe zasady są w niewłaściwej kolejności. Jeśli pojawi się żądanie http://example.com(np. HTTP i nie www), otrzymasz podwójne przekierowanie. Najpierw do https://example.com(pierwsza reguła), a następnie do https://www.example.com(druga reguła). Możesz to naprawić, po prostu odwracając te dwie reguły, ponieważ obie reguły przekierowują na HTTPS niezależnie.
MrWhite
148

Odpowiedź Michalsa działała dla mnie, choć z jedną małą modyfikacją:

Problem:

gdy masz pojedynczy certyfikat bezpieczeństwa witryny , przeglądarka, która próbuje uzyskać dostęp do Twojej strony bez https: // www. (lub którąkolwiek domenę, którą obejmuje Twój certyfikat) wyświetli brzydki czerwony ekran ostrzegawczy, zanim jeszcze otrzyma przekierowanie na bezpieczną i poprawną stronę https.

Rozwiązanie

Najpierw użyj przekierowania na stronę www (lub dowolną domenę objętą certyfikatem), a dopiero potem przekieruj https. Zapewni to, że Twoi użytkownicy nie będą mieli do czynienia z żadnym błędem, ponieważ przeglądarka widzi certyfikat, który nie obejmuje bieżącego adresu 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
źródło
5
+1, ponieważ jest to lepsza opcja dla tego scenariusza, ale należy pamiętać, że nie zapobiegnie to pojawieniu się tego samego problemu, jeśli klient uzyska dostęp https://example.com, ale moim zdaniem jest to najmniej prawdopodobny format, który może wpisać użytkownik. (Przyjęta odpowiedź będzie miała ten sam problem)
Joshua Goossen
@Larzan: To źle. Wyjątek certyfikacyjny występuje tylko dlatego, że wykonujesz 2 prawdziwe przekierowania. Zamień „[L, R = 301]” na „[R = 301]”. Reguły nie są przerywane. L = OSTATNI
pokonaj
Jeśli musisz poradzić sobie https://bez wwwposiadania certyfikatu tylko www, po prostu dodaj tę regułę do rozwiązania: RewriteCond %{HTTP_HOST} !^www\. RewriteCond %{HTTPS} on RewriteRule ^(.*)$ http://www.%{HTTP_HOST}%{REQUEST_URI}[L,R=301] po prostu wraca do httppróby połączenia, https://example.comaby uniknąć błędu certyfikatu.
Eric Burel
1
Te dwie zasady i tak powinny zostać odwrócone (tak jak to zrobiłeś), aby zapobiec podwójnemu przekierowaniu podczas żądania http://example.com(tj. HTTP i brak www)
MrWhite
@EricBurel W tym przypadku nie można uniknąć błędu certyfikatu - uzgadnianie protokołu SSL następuje przed wykonaniem kodu (co jest sednem protokołu SSL). Jeśli Twoje przekierowanie było w stanie wykonać się przed błędem certyfikatu przeglądarki, oznaczałoby to, że żądanie zostało już wykonane przez niepewne połączenie - co byłoby fundamentalną wadą w modelu SSL.
MrWhite
99

Jeśli korzystasz z CloudFlare lub podobnego CDN, otrzymasz błąd nieskończonej pętli dzięki rozwiązaniom% {HTTPS} podanym tutaj. Jeśli jesteś użytkownikiem CloudFlare, musisz użyć tego:

RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Andrzej
źródło
2
Uwaga: obecne porady na stronie pomocy technicznej Cloudflare są nieco inne: support.cloudflare.com/hc/en-us/articles/…
ColinMcDermott
1
Zgadzam się z @ h0mayun, rada Cloudflare daje wyniki w pętli przekierowań, podczas gdy ten kod działa idealnie - dziękuję!
hobailey
2
Korzystam z angularjs na ec2. Rozwiązania wykorzystujące RewriteCond% {HTTPS}! = On dają mi nieskończone przekierowanie (nie do końca pewne, dlaczego). To rozwiązanie, z X-Forwarded-Proto, wydaje się załatwić sprawę. Dziękuję Ci!
Mark Watkins,
3
I zmodyfikowane =httpdo !=httpsnaszych środowisk. X-Forwarded-Protonagłówek nie został zadeklarowany, jeśli http, podobnie !=httpszrobiła sztuczka.
Johnathan Elmore
Dziękuję za ten wgląd! Spędziłem godziny próbując dowiedzieć się, dlaczego {HTTPS}nie działa. Próbowałem, {ENV:HTTPS}a nawet {SERVER_PORT} 443, ale ostatecznie było tak, ponieważ musiałem sprawdzić niestandardowe nagłówki żądań HTTP Cloudflare.
camslice
56

ZŁE ROZWIĄZANIE I DLACZEGO!

Nigdy nie używaj poniższego rozwiązania, ponieważ kiedy używasz ich kodu, jest to coś takiego:

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]

Przeglądarka przechodzi do:

http://example.com

Następnie przekierowuje do:

https://example.com

Następnie przekierowuje do:

https://www.example.com

To za dużo żądań do serwera.

Większość odpowiedzi, nawet zaakceptowanych, ma ten problem.


NAJLEPSZE ROZWIĄZANIE I ODPOWIEDŹ

Ten kod ma [OR]warunek, aby zapobiec podwójnym zmianom w adresie URL!

RewriteEngine on
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule (.*) https://www.example.com%{REQUEST_URI} [R=301,L]
Amir Fo
źródło
3
„ZŁE ROZWIĄZANIE I DLACZEGO!” - Te zasady są po prostu w niewłaściwej kolejności. Odwróć te dwie zasady i będzie poprawne - dostaniesz tylko jedno przekierowanie, a nie dwie.
MrWhite
4
Tak, podany kod skutkuje 2 przekierowaniami - nie kwestionuję tego - mówię tylko, że wystarczy odwrócić te reguły, aby rozwiązać ten problem, żadna inna zmiana nie jest wymagana. („Przyjęta” odpowiedź jest rzeczywiście niepoprawna - co wydaje się być tym, o czym mówisz - dyrektywy są w niewłaściwej kolejności.)
MrWhite
1
Tak, @AmirForsati ma rację. przekierowuje dwa razy i to powinna być zaakceptowana odpowiedź.
Zakir hussain,
4
Możesz użyć tego, jeśli chcesz zachować zmienną nazwy domeny: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,
Przekierowuje mnie to wp-content/cache/page_enhanced/i tak dalej. Jak mogę to naprawić? Edycja: Wygląda na to, że muszę to umieścić na górze .htaccess. Dzięki za skrypt :)
Giacomo
35

Jest to najlepszy sposób, jaki znalazłem dla użytkowników proxy, a nie użytkowników proxy

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
źródło
2
Prawidłowo Jest to najlepszy sposób, jaki znalazłem dla użytkowników proxy, a nie użytkowników proxy +1
Deep 3015
1
To jest najlepsze, ponieważ rozwiązuje wiele przekierowań 301
Niraj Chauhan
1
najlepsze rozwiązanie w historii.
SM Jobayer Alam
1
Świetna odpowiedź. To jedyny, który dla mnie działał. Działa, jeśli jesteś za Cloudflare (chociaż nie mam skonfigurowanych reguł stron w Cloudflare).
jasonco
Jedyne rozwiązanie, które działa na wszystkich moich przypadkach. Ale co, jeśli chcę to zrobić, usuń wszystkie „www”.
FedeKrum
27

Istnieje wiele rozwiązań. Oto link do wiki Apache, która bezpośrednio zajmuje się tym problemem.

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
źródło
Przekonałem RewriteCond %{HTTPS} offsię, RewriteCond %{HTTPS} !=onże zmiana warunku przepisywania z na to przekierowanie zawsze się zdarza, wydaje mi się to lepszą odpowiedzią.
Samuel Hawksby-Robinson
To rozwiązanie należy zaakceptować jako prawidłową odpowiedź! Pracowałem też dla mnie!
AndrewShmig,
11

Aby przekierować http: // lub https: // na https: // www , możesz użyć następującej reguły dla wszystkich wersji 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]

Zauważ, że zmienna% {REQUEST_SCHEME} jest dostępna do użycia od Apache 2.4 .

starkeen
źródło
1
Problem !: Jeśli HTTP_HOST już zawiera www. ale schemat nie jest HTTPS, to kończy się na www.www. u twojego gospodarza.
Jpsy
@Jpsy masz rację. Zaktualizowałem miejsce docelowe przekierowania. Dzięki za wkład.
starkeen
1
To jest prawie to, czego szukałem, ale chcę zachować domenę ogólną, jak w innych przykładach. Czy to możliwe?
cronoklee
8

Jeśli korzystasz z CloudFlare, upewnij się, że używasz czegoś takiego.

# 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

To uratuje Cię od pętli przekierowań i bezpiecznie przekieruje twoją stronę na SSL.

PS Dobrym pomysłem jest sprawdzenie mod_rewrite.c!

Ahmad Awais
źródło
nie przekierowuje https: // theurlwithoutwww.com na https: // www.
tearentthedroids
Jest to faktycznie działające rozwiązanie tylko wtedy, gdy masz wcześniej kilka dyrektyw „dodaj www”. Inne rozwiązania dają mi „do wielu przekierowań”.
Daniel.P.
3
RewriteEngine On 
RewriteCond %{SERVER_PORT} 80 
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R]
Анастасия Ермолик
źródło
2
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]

Uwagi: Upewnij się, że wykonałeś następujące kroki

  1. sudo a2enmod przepisz
  2. usługa sudo apache2 restart
  3. Dodaj następujące w pliku vhost, znajdującym się w /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>

Teraz Twój .htaccess będzie działał, a Twoja strona przekieruje na http: // na https: // www

Kundan Roy
źródło
1

Podobnie jak w rozwiązaniu Amira Forsatiego przekierowanie htaccess na https: // www, ale dla zmiennej nazwy domeny sugeruję:

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]
Bernhard Bodenstorfer
źródło
0

Ustaw w pliku .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]
Adam Kozłowski
źródło
-2

Próbuję pierwszej odpowiedzi i to nie działa ... Ta praca:

<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
źródło