Nginx: wymuś SSL na jednej ścieżce, non-SSL na innych

27

Jak skonfigurować plik conf Nginx, aby wymuszał SSL tylko na jednej ze ścieżek w mojej witrynie, a non-SSL na całej reszcie?

Na przykład chcę, aby wszystkie adresy URL w obszarze / user były https, ale wszystkie pozostałe adresy URL miały postać http.

Do pierwszej części mam:

rewrite ^/user(.*) https://$http_host$request_uri?;

Nie chcę używać „jeśli”. Zakładam, że skorzystałby z kolejności działania, ale nie chcę skończyć w pętli.

pbreitenbach
źródło

Odpowiedzi:

38

W konfiguracji nginx powinieneś mieć dwa obszary „serwerowe”. Jeden dla portu 80 i jeden dla portu 443 (bez SSL i SSL). Po prostu dodaj lokalizację w swojej witrynie bez SSL, aby przekierować na stronę SSL.

server {
    root /var/www/
    location / {
    }
    location /user {
        rewrite ^ https://$host$request_uri? permanent;
    }
}

przekieruje cały ruch, który kończy się na / user na twój serwer https: //.

Następnie na serwerze 443 robisz odwrotnie.

server {
    listen 443;
    root /var/www/
    location / {
        rewrite ^ http://$host$request_uri? permanent;
    }
    location /user {
    }
}
grufftech
źródło
2
Takie podejście jest dobre, ale wpada w kilka typowych pułapek , w szczególności „Zrootuj wewnątrz bloku lokalizacji” i „Opodatkowanie przepisuje”
kolbyjack
1
Redagowałem. Czy to wygląda dobrze? Wyjąłem też 80 i dodałem http_host.
pbreitenbach
W tej konfiguracji połączenie zmienia się z / na ssl / non-ssl, gdy użytkownik porusza się po stronach w witrynie, ssl dla adresów URL zaczyna się od /useri non-ssl dla wszystkich innych adresów. W rezultacie nawet użytkownik wyraźnie wpisuje https://www.example.com/w pasku adresu przeglądarki, wynikowa strona jest http://www.example.com/. Czy istnieje sposób na zaimplementowanie automatycznego przepisywania URL-a między ssl / non-ssl zgodnie z ustawieniami opisanymi w tej odpowiedzi, ale nadal respektuje jawne żądanie ssl, jeśli jest jawnie wpisane przez użytkownika w pasku adresu? Dzięki!
widzenia
@goodbyeera tak. Jeśli chodzi o zmuszenie użytkowników do korzystania z SSL w niektórych obszarach, możemy zastąpić ich protokoły, ale honorować ich wszędzie indziej, po prostu usuwając polecenia przepisywania z konfiguracji serwera 443. Oczywiście teraz, gdy przejdą do zabezpieczonej części, będą nadal przeglądać za pomocą protokołu SSL, gdy pójdą gdzieś indziej, ale pozwala to użytkownikom na korzystanie z SSL od samego początku.
Chuck wysycha
13

Nginx pozwala przetwarzać zarówno HTTP, jak i HTTPS w tym samym serverbloku. Dzięki temu nie musisz powielać dyrektyw dla obu i możesz przekierować ścieżkę, którą chcesz zabezpieczyć

server {
  listen 80 default_server;
  listen 443 ssl;
  ... ssl certificate and other configs ...

  location /user {
    if ($scheme = 'http') {
      rewrite ^ https://$http_host$request_uri? permanent;
    }
  }

  ... your basic configuration ...
}

Pamiętaj, aby nie umieszczać ssl ontam wiersza, ponieważ spowoduje to przerwanie zwykłego protokołu HTTP.

Opcjonalnie możesz przekierować wszystkie pozostałe żądania z HTTPS z powrotem na HTTP w ten sam sposób:

if ($scheme = 'https') {
  rewrite ^ http://$http_host$request_uri? permanent;
}

AKTUALIZACJA : jak uprzejmie zauważa Alexey Ten w sekcji komentarzy, sprawdzanie schemekażdej prośby nie jest zbyt dobrym pomysłem. Powinieneś postępować zgodnie z deklaratywnym sposobem konfiguracji swojego nginx. W takim przypadku zadeklaruj dwa bloki serwera za pomocą przekierowań location, przenieś wspólną logikę do osobnego pliku i includew obu. Zatem odpowiedź GruffTech jest lepsza.

Hnatt
źródło
2
Tworzenie schematu kontroli nginx dla każdego żądania jest nieskuteczne.
Alexey Ten
1
Wiem, że na pytanie udzielono odpowiedzi 3 lata temu, ale znalazłem je, starając się robić to, co stopniowo robiłem i chciałem tylko podzielić się wynikami z ludźmi, którzy będą podążać moimi krokami.
Hnatt,
1
Cóż, powinieneś przeczytać wiki.nginx.org/IfIsEvil
Alexey Ten
1
@AlexeyTen nie jest przypadkiem „kiedy nie da się uniknąć użycia if”? Czy jest jakiś inny sposób na taką samą konfigurację dla HTTP i HTTPS bez powielania dyrektyw?
Hnatt,
2
Użyj includedyrektywy dla wspólnych dyrektyw. Niektóre powielanie jest w porządku.
Alexey Ten