J'ai une page d'inscription sur un sous-domaine comme: https://signup.example.com
Il ne devrait être accessible que via HTTPS, mais je crains que les gens ne tombent dessus en quelque sorte via HTTP et obtiennent un 404.
Mon bloc html/serveur dans nginx ressemble à ceci:
html {
server {
listen 443;
server_name signup.example.com;
ssl on;
ssl_certificate /path/to/my/cert;
ssl_certificate_key /path/to/my/key;
ssl_session_timeout 30m;
location / {
root /path/to/my/Rails/app/public;
index index.html;
passenger_enabled on;
}
}
}
Que puis-je ajouter pour que les personnes qui se rendent sur http://signup.example.com
être redirigé vers https://signup.example.com
? (Pour info je sais qu'il y a Rails plugins qui peuvent forcer SSL
mais j'espérais éviter ça))
Selon pièges nginx , il est légèrement préférable d'omettre la capture inutile, en utilisant $request_uri
au lieu. Dans ce cas, ajoutez un point d'interrogation pour empêcher nginx de doubler les arguments de requête.
server {
listen 80;
server_name signup.mysite.com;
rewrite ^ https://$server_name$request_uri? permanent;
}
La meilleure façon, comme décrit dans le guide officiel , est d'utiliser la directive return
:
server {
listen 80;
server_name signup.mysite.com;
return 301 https://$server_name$request_uri;
}
C'est la manière correcte et la plus efficace si vous voulez tout garder dans un seul bloc serveur:
server {
listen 80;
listen [::]:80;
listen 443 default_server ssl;
server_name www.example.com;
ssl_certificate /path/to/my/cert;
ssl_certificate_key /path/to/my/key;
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
}
Tout le reste ci-dessus, en utilisant "réécriture" ou "si ssl_protocol" etc est plus lent et pire.
Voici la même chose, mais encore plus efficace, en exécutant uniquement la réécriture sur le protocole http, cela évite d'avoir à vérifier la variable $ schéma à chaque demande. Mais sérieusement, c'est une chose si mineure que vous n'avez pas besoin de les séparer.
server {
listen 80;
listen [::]:80;
server_name www.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 default_server ssl;
server_name www.example.com;
ssl_certificate /path/to/my/cert;
ssl_certificate_key /path/to/my/key;
}
Si vous utilisez la nouvelle définition de serveur double HTTP et HTTPS, vous pouvez utiliser les éléments suivants:
server {
listen 80;
listen [::]:80;
listen 443 default ssl;
server_name www.example.com;
ssl_certificate /path/to/my/cert;
ssl_certificate_key /path/to/my/key;
if ($ssl_protocol = "") {
rewrite ^ https://$server_name$request_uri? permanent;
}
}
Cela semble fonctionner pour moi et ne provoque pas de boucles de redirection.
Modifier:
Remplacé:
rewrite ^/(.*) https://$server_name/$1 permanent;
avec la ligne de réécriture de Pratik.
Encore une autre variante, qui préserve l'en-tête Host: request et suit l'exemple "GOOD" sur pièges nginx :
server {
listen 10.0.0.134:80 default_server;
server_name site1;
server_name site2;
server_name 10.0.0.134;
return 301 https://$Host$request_uri;
}
Voici les résultats. Notez que l'utilisation de $server_name
au lieu de $Host
redirigerait toujours vers https://site1
.
# curl -Is http://site1/ | grep Location
Location: https://site1/
# curl -Is http://site2/ | grep Location
Location: https://site2/
# curl -Is http://site1/foo/bar | grep Location
Location: https://site1/foo/bar
# curl -Is http://site1/foo/bar?baz=qux | grep Location
Location: https://site1/foo/bar?baz=qux
Assurez-vous de définir "sécurisé" sur tous les cookies, sinon ils seront envoyés sur la demande HTTP et pourraient être récupérés par un outil comme Firesheep.
server {
listen x.x.x.x:80;
server_name domain.tld;
server_name www.domian.tld;
server_name ipv4.domain.tld;
rewrite ^ https://$server_name$request_uri? permanent;
}
Cela fonctionne mieux je pense. x.x.x.x fait référence à l'IP de votre serveur. Si vous travaillez avec Plesk 12, vous pouvez le faire en modifiant le fichier "nginx.conf" dans le répertoire "/var/www/vhosts/system/domain.tld/conf" pour le domaine de votre choix. N'oubliez pas de redémarrer le service nginx après avoir enregistré la configuration.
Je pense que c'est la solution la plus simple. Force le trafic non HTTPS et non WWW vers HTTPS et www uniquement.
server {
listen 80;
listen 443 ssl;
server_name domain.tld www.domain.tld;
# global HTTP handler
if ($scheme = http) {
return 301 https://www.domain.tld$request_uri;
}
# global non-WWW HTTPS handler
if ($http_Host = domain.tld) {
return 303 https://www.domain.tld$request_uri;
}
}
EDIT - Apr 2018: La solution sans IF peut être trouvée dans mon article ici: https://stackoverflow.com/a/36777526/6076984