Nginx: принудительно использовать SSL на одном пути, не-SSL на других

27

Как настроить файл conf Nginx для принудительной установки SSL только по одному из путей на моем сайте и не-SSL по всем остальным?

Например, я хочу, чтобы все URL-адреса в / user были https, а все остальные URL-адреса - http.

Для первой части у меня есть:

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

Я не хочу использовать «если». Я предполагаю, что это будет использовать порядок операций, но я не хочу оказаться в цикле.

pbreitenbach
источник

Ответы:

38

В вашей конфигурации nginx у вас должно быть две «серверные» области. Один для порта 80 и один для порта 443 (без SSL и SSL). Просто добавьте местоположение на вашем веб-сайте без SSL, чтобы перенаправить на свою страницу SSL.

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

он перенаправит весь трафик, который заканчивается в / user, на ваш сервер https: //.

Затем на вашем сервере 443 вы делаете обратное.

server {
    listen 443;
    root /var/www/
    location / {
        rewrite ^ http://$host$request_uri? permanent;
    }
    location /user {
    }
}
grufftech
источник
2
Этот подход хорош, но он подпадает под несколько общих ловушек , а именно: «Корень внутри блока местоположения» и «
Переписывание налогов
1
Я редактировал. Это выглядит хорошо? Я также вынул слушать 80 и добавил http_host.
pbreitenbach
В этой конфигурации соединение переключается с / на ssl / non-ssl, когда пользователь перемещается по страницам на сайте, ssl для URL-адресов начался с /userи non-ssl для всех других URL-адресов. В результате даже пользователь явно вводит https://www.example.com/в адресную строку браузера полученную страницу http://www.example.com/. Есть ли способ реализовать авто-перезапись URL-адресов между ssl / non-ssl, что достигается настройками, описанными в этом ответе, но при этом уважать явный запрос ssl, если он явно введен пользователем в адресной строке? Благодарность!
свидания
@goodbyeera, да. Если идея состоит в том, чтобы заставить пользователей использовать SSL в определенных областях, мы можем переопределить их протоколы там, но соблюдать их везде, просто удалив команды перезаписи из конфигурации сервера 443. Конечно, теперь, когда они переходят в защищенную часть, они по-прежнему будут просматривать SSL, когда уходят куда-то еще, но это позволяет людям выбирать использование SSL с самого начала.
Чак
13

Nginx позволяет обрабатывать HTTP и HTTPS в одном serverблоке. Таким образом, вам не нужно дублировать директивы для обоих и перенаправить путь, который вы хотите защитить

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

Будьте уверены, чтобы не поставить ssl onстроку там, потому что это сломает простой HTTP.

При желании вы можете перенаправить все другие запросы из HTTPS обратно в HTTP таким же образом:

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

ОБНОВЛЕНИЕ : как любезно указывает Алексей Тен в разделе комментариев, проверка schemeкаждого запроса не очень хорошая идея. Вы должны следовать декларативному способу настройки вашего nginx. В этом случае объявите два серверных блока с перенаправлениями location, переместите общую логику в отдельный файл и includeв оба. Так что ответ GruffTech лучше.

Hnatt
источник
2
Неэффективно создавать схему проверки nginx для каждого запроса.
Алексей Тен
1
Я знаю, что на вопрос был дан ответ 3 года назад, но я нашел его, пытаясь сделать то, что делал постепенно, и просто хотел поделиться своими результатами с людьми, которые будут следовать моим шагам.
Hnatt
1
Ну, вы должны прочитать wiki.nginx.org/IfIsEvil
Алексей Тен
1
@AlexeyTen разве это не тот случай, "когда вы не можете избежать использования if"? Есть ли другой способ иметь одинаковую конфигурацию для HTTP и HTTPS без дублирования директив?
Hnatt
2
Используйте includeдирективу для общих директив. Некоторое дублирование в порядке.
Алексей Тен