Nginx auth_request: закрыть файлы проверкой доступа

Категория: Nginx · Обновлено:

auth_request отправляет внутренний подзапрос перед обработкой основного запроса. Ответ 2xx разрешает доступ, 401 и 403 запрещают, а любой другой статус даёт клиенту 500. Так Nginx проверяет сессию или токен через отдельный сервис и не отдаёт статику или проксированный ресурс без подтверждения.

Проверить доступ перед проксированием

Текст
upstream auth_service {
    server 127.0.0.1:9001;
}

upstream files_service {
    server 127.0.0.1:9002;
}

server {
    listen 80;
    server_name files.example.com;

    location = /_auth {
        internal;
        proxy_pass http://auth_service/verify;
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
        proxy_set_header X-Original-URI $request_uri;
    }

    location /files/ {
        auth_request /_auth;
        auth_request_set $auth_user $upstream_http_x_user_id;
        proxy_set_header X-User-Id $auth_user;
        proxy_pass http://files_service;
    }
}

Директива internal запрещает обращаться к /_auth снаружи: этот location доступен только как подзапрос. proxy_pass_request_body off и пустой Content-Length не передают тело основного запроса сервису авторизации. Заголовок X-Original-URI помогает проверить, к какому именно пути запрашивается доступ.

auth_request_set сохраняет заголовок из ответа проверки, чтобы передать идентификатор пользователя во внутренний сервис. Не доверяйте входящему заголовку X-User-Id от клиента: перезаписывайте его значением из доверенного ответа, как в примере.

Проверка выполняется на каждый запрос, поэтому сервис авторизации должен отвечать быстро; кешируйте результат в нём, а не в Nginx. Для защищённого location отключите кеширование ответа, если права могут измениться между запросами. Директиву можно ставить в http, server или location; модуль ngx_http_auth_request_module входит в стандартные сборки Nginx, но проверьте его наличие через nginx -V.

Если проверка возвращает 401, клиенту можно показать страницу входа через error_page 401 = @login;. Не добавляйте auth_request в location самой проверки — получится рекурсивный подзапрос.

Документация: ngx_http_auth_request_module.