Конфигурация Nginx: как использовать аутентификацию auth_basic, если ssl_client_certificate не предоставлено?
Я пытаюсь настроить сервер Nginx следующим образом:
Во-первых, сервер должен проверить, предоставил ли пользователь сертификат SSL клиента (через ssl_client_certificate). Если сертификат SSL предоставлен, то предоставите доступ к сайту,
Если сертификат SSL НЕ предоставляется, попросите пользователя ввести пароль и войти в систему через auth_basic.
Мне удалось настроить оба метода аутентификации одновременно. Но этот конфиг лишний.
Чтобы проверить, предоставил ли пользователь свой SSL-сертификат, я пытаюсь настроить конфигурацию следующим образом:
18: if ($ssl_client_verify != SUCCESS) {
19: auth_basic "Please login";
20: auth_basic_user_file .passfile;
21: }
Но Nginx возвращает ошибку:
Директива auth_basic не разрешена здесь... /ssl.conf: 19
Как я могу установить условие в этом случае?
Ответы
Ответ 1
Вы можете установить конфигурацию auth_basic
в предложении if
следующим образом:
server {
listen 443;
auth_basic_user_file .htpasswd;
ssl_client_certificate ca.cert;
ssl_verify_client optional;
...
location / {
...
if ($ssl_client_verify = SUCCESS) {
set $auth_basic off;
}
if ($ssl_client_verify != SUCCESS) {
set $auth_basic Restricted;
}
auth_basic $auth_basic;
}
}
Теперь аутентификация возвращается к HTTP Basic, если сертификат клиента не предоставлен (или если проверка не выполнена).
Ответ 2
Я не могу проверить это сейчас, но что-то вроде этой работы?
server {
listen 80;
server_name www.example.com example.com;
rewrite ^ https://$server_name$request_uri? permanent;
}
server {
listen 443;
...
if ($ssl_client_verify != SUCCESS) {
rewrite ^ http://auth.example.com/ permanent;
}
location / {
...
}
}
server {
listen 80;
server_name auth.example.com;
location / {
auth_basic "Please login";
auth_basic_user_file .passfile;
}
}
Итак, в основном:
- Примите все начальные запросы (на порт 80 для любого имени, которое вы используете) и перепишите в ssl
- Проверьте, проверен ли клиент.
- Если нет, перепишите в альтернативный домен, который использует базовый auth
Как я уже сказал, я не могу проверить это прямо сейчас, но я постараюсь обойти это! Дайте мне знать, если это поможет, мне интересно узнать, работает ли это.
Ответ 3
Nginx не может отказаться от базовой проверки подлинности, когда клиентский сертификат завершается с ошибкой. В качестве альтернативы вы можете использовать переменные для ограничения доступа:
location / {
if ($ssl_client_verify = "SUCCESS") {
set $authorized 1;
}
if ($authorized != 1) {
error_page 401 @basicauth;
return 401;
}
}
location @basicauth {
auth_basic "Please login";
auth_basic_user_file .passfile;
set $authorized 1;
rewrite /(.*) /$1;
}
* Имейте в виду, что IfIsEvil и эти правила могут работать некорректно или мешать другим частям более крупной конфигурации.
Ответ 4
Забудьте об этом, это не сработает.
Причина, по которой он терпит неудачу, заключается в том, что if
он не является частью общего конфигурационного модуля, как следует полагать. if
это часть модуля перезаписи, а auth_basic
- еще один модуль. У вас просто не может быть динамических vhosts с базовым auth.
С другой стороны...
У вас могут быть динамические vhosts со своими страницами ошибок. Следующий пример предназначен для пользовательской страницы 404, но вы можете реализовать ее в своем коде.
server {
listen 80;
server_name _;
set $site_root /data/www/$host;
location / {
root $site_root;
}
error_page 404 =404 /404.html;
location /404.html {
root $site_root/error_files;
internal;
error_page 404 =404 @fallback_404;
}
location @fallback_404 {
root /var/www/;
try_files /404.html =404;
internal;
}
error_log /var/log/nginx/error.log info;
access_log /var/log/nginx/access.log;
}
Что происходит...
- вы сообщаете Nginx использовать
/404.html
в случае HTTP_NOT_FOUND
. - изменение
root
каталога местоположения в соответствии с error_pages
веб-сайта. - внутреннее перенаправление
- возвращение 404 http-кода
- настройте резервную страницу 404 в
location @fallback_404
: в этом месте root
изменен на /var/www/
поэтому он будет читать файлы с этого пути вместо $site_root
- на последнем этапе код возвращает
/var/www/404.html
если он существует с 404 http-кодом.
ПРИМЕЧАНИЕ. Согласно документации Nginx:
Указывает, что данное местоположение может использоваться только для внутренних запросов. Для внешних запросов возвращается ошибка клиента 404 (не найдена). Внутренние запросы:
- запросы перенаправляются директивами error_page, index, random_index и try_files;
- запросы перенаправляются с помощью поля заголовка ответа "X-Accel-Redirect" от восходящего сервера;
- подзапросы, сформированные командой "включить виртуальную" модуля ngx_http_ssi_module и директивами модуля ngx_http_addition_module;
- запросы, измененные директивой rewrite.
Также:
Для каждого запроса существует ограничение на 10 внутренних перенаправлений для предотвращения циклов обработки запросов, которые могут возникать в неправильных конфигурациях. Если это ограничение достигнуто, возвращается ошибка 500 (Внутренняя ошибка сервера). В таких случаях сообщение "переписать или внутренний цикл перенаправления" можно увидеть в журнале ошибок.
Проверьте эту ссылку для получения дополнительной информации, надеюсь, что это поможет.