Nginx: SSL auf einem Pfad erzwingen, Nicht-SSL auf anderen

27

Wie richte ich die Nginx-Conf-Datei so ein, dass nur einer der Pfade auf meiner Site SSL und der Rest Nicht-SSL erzwungen wird?

Ich möchte zum Beispiel, dass alle URLs unter / user https lauten und alle anderen URLs http lauten.

Für den ersten Teil habe ich:

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

Ich möchte nicht "if" verwenden. Ich nehme an, es würde die Reihenfolge der Operationen ausnutzen, aber ich möchte nicht in eine Schleife geraten.

pbreitenbach
quelle

Antworten:

38

In Ihrer Nginx-Konfiguration sollten Sie zwei "Server" -Bereiche haben. Eine für Port 80 und eine für Port 443 (nicht SSL und SSL). Fügen Sie einfach einen Ort auf Ihrer Nicht-SSL-Website hinzu, um zu Ihrer SSL-Seite umzuleiten.

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

Der gesamte Datenverkehr, der bei / user landet, wird an Ihren https: // Server weitergeleitet.

Dann machen Sie auf Ihrem 443-Server das Gegenteil.

server {
    listen 443;
    root /var/www/
    location / {
        rewrite ^ http://$host$request_uri? permanent;
    }
    location /user {
    }
}
grufftech
quelle
2
Dieser Ansatz ist gut, fällt aber in einige gängige Fallstricke , insbesondere "Root inside location block" und "
Taxing rewrites
1
Ich habe bearbeitet. Sieht es ok aus Ich habe auch Listen 80 rausgenommen und http_host hinzugefügt.
pbreitenbach
Bei dieser Konfiguration wechselt die Verbindung von / zu ssl / non-ssl, wenn ein Benutzer auf den Seiten der Site navigiert, ssl für URLs, die mit /userund non-ssl für alle anderen URLs beginnen. Selbst wenn der Benutzer https://www.example.com/die Adresszeile des Browsers explizit eingibt, wird die resultierende Seite angezeigt http://www.example.com/. Gibt es eine Möglichkeit, das automatische Url-Umschreiben zwischen ssl / non-ssl zu implementieren, wie es durch die in dieser Antwort beschriebenen Einstellungen erreicht wird, aber trotzdem die explizite ssl-Anforderung zu respektieren, wenn sie vom Benutzer explizit in die Adressleiste eingegeben wird? Vielen Dank!
Wiedersehen,
@ goodbyeera ja. Wenn die Benutzer gezwungen werden sollen, in bestimmten Bereichen SSL zu verwenden, können wir ihre Protokolle dort außer Kraft setzen, sie aber überall anders berücksichtigen, indem wir einfach die Umschreibebefehle aus der 443-Serverkonfiguration entfernen. Natürlich surfen sie jetzt, wenn sie zu einem gesicherten Teil gehen, immer noch mit SSL, wenn sie an einen anderen Ort gehen, aber es ermöglicht den Leuten, SSL von Anfang an zu verwenden.
Chuck Dries
13

Nginx ermöglicht die Verarbeitung von HTTP und HTTPS innerhalb desselben serverBlocks. Sie müssen also keine Anweisungen für beide duplizieren und können den Pfad, den Sie sichern möchten, umleiten

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 ...
}

Achten Sie darauf , nicht zu setzen ssl ondort Linie , weil es wird schlicht HTTP brechen.

Optional können Sie alle anderen Anforderungen von HTTPS auf dieselbe Weise zurück an HTTP umleiten:

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

UPDATE : Wie Alexey Ten freundlicherweise in den Kommentaren ausführt, schemeist es keine besonders gute Idee , jede Anfrage zu prüfen . Sie sollten die deklarative Methode zur Konfiguration Ihres Nginx befolgen. In diesem Fall deklarieren Sie zwei Serverblöcke mit Weiterleitungen von location, verschieben Sie die gemeinsame Logik in eine separate Datei und includein beide. Die Antwort von GruffTech ist also besser.

Hnatt
quelle
2
Es ist ineffektiv, für jede Anfrage ein Nginx-Prüfschema zu erstellen.
Alexey Ten
1
Ich weiß, dass die Frage vor drei Jahren beantwortet wurde, aber ich fand sie, als ich mich abmühte, das zu tun, was ich nach und nach tat, und wollte nur meine Ergebnisse mit Leuten teilen, die meinen Schritten folgen.
Hnatt
1
Nun, du solltest wiki.nginx.org/IfIsEvil
Alexey Ten
1
@AlexeyTen ist es nicht der Fall, "wenn Sie nicht vermeiden können, ein Wenn zu verwenden"? Gibt es eine andere Möglichkeit, die gleiche Konfiguration für HTTP und HTTPS zu verwenden, ohne Anweisungen zu duplizieren?
Hnatt
2
Verwenden Sie die includeDirektive für allgemeine Direktiven. Einige Wiederholungen sind in Ordnung.
Alexey Ten