Вопрос или проблема
Я пытаюсь настроить nginx для выполнения аутентификации пользователей перед доступом к ресурсу. В настоящее время моя конфигурация выглядит следующим образом:
server {
listen 80 default_server;
listen [::]:80 default_server;
location = /test {
satisfy any;
auth_basic "test";
auth_basic_user_file "/usr/local/nginx/htpasswd";
auth_request /auth;
proxy_pass http://localhost:9000/;
}
location = /auth {
proxy_pass http://192.168.111.101:8080/auth;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
}
}
Итак, я хочу, чтобы nginx запрашивал у пользователя пароль, используя процедуру “auth_basic”. (это не сработает, так как пользователь не находится в файле auth_basic_user_file)
Затем nginx должен попробовать “auth_request” и также предоставить имя пользователя/пароль, использованные в “auth_basic”. То же решение, что и здесь: https://stackoverflow.com/questions/23299623/nginx-authentication-with-auth-request-module, однако кажется, что nginx в некотором смысле отдает предпочтение “auth_request”, так что это выполняется первым, а “auth_basic” выполняется после.
Есть идеи, что я делаю не так?
Самое важное для загрузки файла через POST:
proxy_pass_request_body off;
proxy_set_header Content-Length "";
Если вы только получаете, то вышеуказанное не нужно добавлять.
HTTP по своей сути является безсостоявым. Основная аутентификация полагается на состояние, сохраняемое в браузере, и отправляемое обратно на сервер. Сервер должен сообщить браузеру, что это должно быть включено. С механизмом auth_request состояние есть, но механизм непрозрачен для nginx.
Учитывая это, в nginx нет механизма для различения клиента, который еще не пытался выполнить базовую аутентификацию, и клиента, который был аутентифицирован через механизм auth_request.
Если вы просто хотите предоставить два разных метода входа, то вам нужно реализовать их обоих в поставщике аутентификации (или мультиплексировать через поставщика аутентификации), а не в nginx.
Тем не менее, если вы только хотите использовать базовую аутентификацию для неинтерактивного доступа, то вы можете использовать наличие заголовка “Authorization” в качестве индикатора для nginx.
Ответ или решение
Для успешной настройки аутентификации в Nginx с использованием auth_request
и auth_basic
, необходимо понимать, как работают эти механизмы и как их правильно конфигурировать, чтобы избежать конфликта между ними. Проблема, с которой вы сталкиваетесь, заключается в том, что auth_request
вызывается раньше, чем auth_basic
, и это создает сложность для обработки аутентификации пользователей по обоим методам.
Решение проблемы
-
Основы конфигурации:
Обратите внимание, что при использовании
auth_request
, Nginx не может различить, был ли клиент уже аутентифицирован при помощиauth_basic
. Таким образом, если вы хотите использовать оба метода аутентификации, вам нужно управлять логикой аутентификации через вашу собственную аутентификационную систему (допустим, через API), которая должна поддерживать оба метода. -
Настройка конфигурации:
Пример более правильной конфигурации может выглядеть следующим образом:
server { listen 80 default_server; listen [::]:80 default_server; location = /test { satisfy any; auth_basic "Restricted Access"; auth_basic_user_file "/usr/local/nginx/htpasswd"; auth_request /auth; proxy_pass http://localhost:9000/; # Обратите внимание, что следующие настройки нужны для POST запросов proxy_pass_request_body off; proxy_set_header Content-Length ""; proxy_set_header X-Original-URI $request_uri; } location = /auth { internal; # Эта локация будет использоваться только внутренне proxy_pass http://192.168.111.101:8080/auth; proxy_pass_request_body off; proxy_set_header Content-Length ""; proxy_set_header X-Original-URI $request_uri; # Перенименование или добавление заголовков авторизации (по желанию) proxy_set_header Authorization $http_authorization; } }
-
Обработка заголовков авторизации:
Важно убедиться, что заголовок
Authorization
передается в запросе к вашемуauth
серверу. Ваша конфигурация выше уже включает это с помощьюproxy_set_header Authorization $http_authorization;
. Это позволит вашему аутентификационному серверу понимать, какие учетные данные были переданы пользователем, и проверять их. -
Обработка состояния:
Поскольку
auth_request
не сохраняет состояние сессии, вам может понадобиться подход на стороне вашего аутентификационного сервера, который сможет корректно обрабатывать запросы, пришедшие без аутентификации (auth_basic
). Рекомендуется использовать сервер Auth, который проверяет наличие заголовкаAuthorization
, и если он отсутствует, возвращает ошибку 401 (Unauthorized) или 403 (Forbidden), что заставит клиентское приложение предложить пользователю ввести свои учетные данные.
Заключение
В результате, вам нужно организовать логику аутентификации на стороне сервера, где вы обрабатываете аутентификацию как по методу auth_basic
, так и через auth_request
. Это даст вам гибкость и позволит клиентам использовать оба метода в зависимости от их потребностей. Если вы хотите достичь более сложной архитектуры аутентификации, вы можете рассмотреть внедрение системы авторизации на стороне сервера, которая сможет управлять различными методами аутентификации более эффективно.