У меня есть страница регистрации в субдомене, например: https://signup.example.com
Он должен быть доступен только через HTTPS, но я беспокоюсь, что люди могут каким-то образом наткнуться на него через HTTP и получить 404.
Мой блок html / server в nginx выглядит так:
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;
}
}
}
Что я могу добавить, чтобы люди, которые заходят в http://signup.example.com
перенаправить на https://signup.example.com
? (К вашему сведению, я знаю, что есть плагины Rails, которые могут SSL
но надеялся этого избежать)
Лучший способ, описанный в официальное руководство с помощью return
директива:
server {
listen 80;
server_name signup.mysite.com;
return 301 https://$server_name$request_uri;
}
В соответствии с подводные камни nginx, немного лучше опустить ненужный захват, используя $request_uri
вместо. В этом случае добавьте вопросительный знак, чтобы nginx не удвоил любые аргументы запроса.
server {
listen 80;
server_name signup.mysite.com;
rewrite ^ https://$server_name$request_uri? permanent;
}
Это правильный и наиболее эффективный способ, если вы хотите сохранить все в одном серверном блоке:
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;
}
}
Все остальное выше, используя «rewrite» или «if ssl_protocol» и т. Д., Работает медленнее и хуже.
Здесь то же самое, но даже более эффективно, поскольку выполняется перезапись только по протоколу http, это позволяет избежать проверки переменной $ scheme при каждом запросе. А если серьезно, это такая мелочь, что не нужно их разделять.
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;
}
Если вы используете новое определение двойного сервера HTTP и HTTPS, вы можете использовать следующее:
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;
}
}
Это работает для меня и не вызывает циклов перенаправления.
Редактировать:
Заменены:
rewrite ^/(.*) https://$server_name/$1 permanent;
с линией перезаписи Pratik.
Еще один вариант, который сохраняет заголовок запроса Host: и следует примеру "ХОРОШО" на подводные камни 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;
}
Вот результаты. Обратите внимание, что использование $server_name
вместо того $host
всегда перенаправлял на 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
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;
}
Думаю, это работает лучше. x.x.x.x относится к IP-адресу вашего сервера. Если вы работаете с Plesk 12, вы можете сделать это, изменив файл «nginx.conf» в каталоге «/var/www/vhosts/system/domain.tld/conf» для любого домена, который вам нужен. Не забудьте перезапустить службу nginx после сохранения конфигурации.
Думаю, это самое простое решение. Принудительно направляет трафик как без HTTPS, так и без WWW только на HTTPS и www.
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;
}
}
РЕДАКТИРОВАТЬ - апр 2018: Решение без IF можно найти в моем сообщении здесь: https://stackoverflow.com/a/36777526/6076984