Nginx: forcer SSL sur un chemin, non SSL sur les autres

27

Comment configurer le fichier de conf Nginx pour forcer SSL sur un seul des chemins de mon site et non SSL sur tous les autres?

Par exemple, je veux que toutes les URL sous / user soient https mais que toutes les autres URL soient http.

Pour la première partie, j'ai:

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

Je ne veux pas utiliser "si". Je suppose que cela profiterait de l'ordre de fonctionnement, mais je ne veux pas finir dans une boucle.

pbreitenbach
la source

Réponses:

38

Dans votre configuration nginx, vous devriez avoir deux zones "serveur". Un pour le port 80 et un pour le port 443 (non SSL et SSL). Ajoutez simplement un emplacement dans votre site Web non SSL pour rediriger vers votre page SSL.

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

il transmettra tout le trafic qui aboutit à / user à votre serveur https: //.

Ensuite, dans votre serveur 443, vous faites le contraire.

server {
    listen 443;
    root /var/www/
    location / {
        rewrite ^ http://$host$request_uri? permanent;
    }
    location /user {
    }
}
grufftech
la source
2
Cette approche est bonne, mais elle se heurte à quelques pièges courants , en particulier "Root inside block block" et "
Taxing rewrites
1
J'ai édité. Ça a l'air bien? J'ai également retiré Listen 80 et ajouté http_host.
pbreitenbach
Avec cette configuration, la connexion bascule de / vers ssl / non-ssl lorsqu'un utilisateur navigue sur les pages du site, ssl pour les URL a commencé avec /useret non-ssl pour toutes les autres URL. Par conséquent, même l'utilisateur tape explicitement https://www.example.com/dans la barre d'adresse du navigateur, la page résultante est http://www.example.com/. Existe-t-il un moyen d'implémenter la réécriture auto-url entre ssl / non-ssl comme atteint par les paramètres décrits dans cette réponse, mais toujours respecter la demande ssl explicite si elle est explicitement tapée par l'utilisateur dans la barre d'adresse? Merci!
revoir le
@ goodbyeera ouais. Si l'idée est de forcer les utilisateurs à utiliser SSL dans certains domaines, nous pouvons y remplacer leurs protocoles mais les honorer partout ailleurs en supprimant simplement les commandes de réécriture de la configuration du serveur 443. Bien sûr, maintenant, lorsqu'ils accèdent à une partie sécurisée, ils continueront à naviguer avec SSL lorsqu'ils iront ailleurs, mais cela permet aux gens de choisir d'utiliser SSL dès le départ.
Chuck Dries
13

Nginx permet de traiter à la fois HTTP et HTTPS dans le même serverbloc. Ainsi, vous n'avez pas à dupliquer les directives pour les deux et pouvez rediriger le chemin que vous souhaitez sécuriser

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

Assurez-vous de ne pas y mettre de ssl onligne car cela cassera le HTTP simple.

Facultativement, vous pouvez rediriger toutes les autres demandes de HTTPS vers HTTP de la même manière:

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

MISE À JOUR : comme le souligne gentiment Alexey Ten dans la section des commentaires, vérifier schemechaque demande n'est pas une idée très brillante. Vous devez suivre la manière déclarative de configurer votre nginx. Dans ce cas, déclarez deux blocs serveur avec des redirections par location, déplacez la logique commune vers un fichier séparé et includedans les deux. La réponse de GruffTech est donc meilleure.

Hnatt
la source
2
Il est inefficace de faire un schéma de vérification nginx pour chaque demande.
Alexey Ten
1
Je sais que la question a été répondue il y a 3 ans, mais je l'ai trouvée tout en luttant pour faire ce que j'ai fait progressivement et je voulais juste partager mes résultats avec des gens qui suivront mes pas.
Hnatt
1
Eh bien, vous devriez lire wiki.nginx.org/IfIsEvil
Alexey Ten
1
@AlexeyTen n'est-ce pas le cas "quand vous ne pouvez pas éviter d'utiliser un if"? Existe-t-il un autre moyen d'avoir la même configuration pour HTTP et HTTPS sans dupliquer les directives?
Hnatt
2
Utilisez la includedirective pour les directives communes. Une certaine duplication est OK.
Alexey Ten