Nginx 的 auth_request_set 和 more_set_input_headers 行为不一致

Nginx 的 auth_request_set 和 more_set_input_headers 行为不一致

我正在尝试使用授权请求模块与more_set_input_headers自动让我的用户登录到网络应用程序。

基本上,它的工作原理如下:

  1. 用户有一些用于对他们进行身份验证的会话 cookie。
  2. 我有一个 PHP 脚本(auth.php),用于验证 cookie 并返回其正确的用户名作为响应标头。
  3. Nginx 使用 auth_request 调用 auth.php,并将用户名设置在变量中。
  4. 然后,Nginx 使用设置为正确用户名的请求标头来调用 Web 应用程序。
  5. Web 应用程序读取标题,并让用户登录。

这可以工作,但奇怪的是不一致。问题是,当用户访问 /app/ 上的 Web 应用程序时,它可以工作,但当在 /app/index.php 上访问该应用程序时,它永远不会收到来自 nginx 的标头。

我创建了一个可以重现该错误的模拟配置。

Nginx 站点配置:

server {
    server_name www.example.com
    index index.php index.html;

    # --- Internal auth
    location /auth {
        internal;
        root /var/www/sf;

        location /auth/auth.php {
            fastcgi_pass unix:/var/run/php5-fpm.sock;
            include includes/fastcgi_params;

            fastcgi_pass_request_body off;
            fastcgi_param CONTENT_LENGTH 0;
        }

        location /auth {
            deny all;
        }
    }

    location / {

        auth_request /auth/auth.php;

        auth_request_set $auth_header $upstream_http_x_auth_header;
        more_set_input_headers 'X-Test-Header: $auth_header';

        location /app {
            root /var/www/sf;

            # Allow these locations
            location = /app/ {
                allow all;
            }

            location /app/index.php {
                fastcgi_pass unix:/var/run/php5-fpm.sock;
                include includes/fastcgi_params;
            }

            # Deny everything else
            location /app/ {
                deny all;
            }
        }

    }
}

/var/www/sf/auth/auth.php:

<?php

// Mock precondition checker
function is_allowed() {
    return true;
}

// Set the default response code
http_response_code(403);

if(!is_allowed())
    exit();

// Return our header and the OK response code
header("X-Auth-Header: myusername");
http_response_code(200);

/var/www/sf/app/index.php:

<?php

if(empty($_SERVER["HTTP_X_TEST_HEADER"]))
    exit("No header was supplied by nginx.");

exit("Nginx supplied header value: ". $_SERVER["HTTP_X_TEST_HEADER"]);

对 /app/ 执行 GET 请求时的响应:

Nginx supplied header value: myusername

对 /app/index.php 执行 GET 请求时的响应:

No header was supplied by nginx.

有人知道这里发生了什么事吗?

我正在使用 Debian Wheezy 和来自 DotDeb 的 nginx-extras 包(1.6.0-1~dotdeb.1)。

(小提示:当您将 'more_set_input_headers 'X-Test-Header: $auth_header';' 替换为 'more_set_input_headers 'X-Test-Header: foobar';' 时,Web 应用程序始终会收到一个标头)

答案1

这种行为可能是因为 more_set_input_headers处理程序是在访问阶段(auth_request起作用的地方)之前执行的,因此只有在内部重定向时才会更改请求。

解决问题的方法是停止使用more_set_input_headers (无论如何这都是非常错误的,请求标头不应该更改)并改用本机fastcgi_param

fastcgi_param HTTP_X_TEST_HEADER $auth_header;

复制自http://mailman.nginx.org/pipermail/nginx/2014-June/044281.html

相关内容