2016-12-15 36 views
1

TL:博士,如果请求使用nginx的error_page指令重定向,我怎么能确保自定义头与此重定向通过。Nginx的传递HTTP头通过error_page重定向

我目前正在实现一个系统,其中nginx对LDAP服务器进行身份验证并充当反向代理。它基于此https://www.nginx.com/blog/nginx-plus-authenticate-users/ 它的工作方式是,它有一个全能的服务器模块,它将请求发送到在另一个端口上运行的认证页面,这会根据cookie的内容返回403或200 。如果这是403,则用户被发送到登录页面(如果200到达目的地)。

nginx conf的示例如下: location/{ auth_request/auth-proxy;

 # redirect 401 to login form 
     error_page 401 =200 /login; 

     proxy_pass http://backend/; 
    } 

    location /login { 
     proxy_pass http://backend/login; 
     # Login service returns a redirect to the original URI 
     # and sets the cookie for the ldap-auth daemon 
     proxy_set_header X-Target $request_uri; 
    } 

    location = /auth-proxy { 
     internal; 

     # The ldap-auth daemon listens on port 8888, as set 
     # in nginx-ldap-auth-daemon.py. 
     # Change the IP address if the daemon is not running on 
     # the same host as NGINX/NGINX Plus. 
     proxy_pass http://127.0.0.1:8888; 

的问题是,我做的改变,使认证兼职并返回一个403码,而不管该cookie是否有效。不过,我想让用户知道登录页面发生了这种情况,因此Python身份验证代码会设置带有错误值的X-authenticationfail标头。

我检查了这部作品通过使用curl发送超时cookie来验证码,并读取头回来。然而,当登录python代码被调用时,这个头信息已经消失。我认为这是由于nginx不转发它。我试图包含“proxy_set_header X-authenticationfail $ http_x_authenticationfail;”,“add_header X-authenticationfail”这样的行“test”always;“在error_page指令之前,但这不起作用。我也尝试过在同一地点使用“proxy_pass_header X-authenticationfail”,但这也失败了。

服务器块具有“上proxy_pass_request_headers”设置设置“上underscores_in_headers”,和。在登录块中,放置“proxy_set_header X-authenticationfail”testvalue“;”获得了登录python代码的价值,并从那里回到浏览器。

感谢您获得这么多!

+0

简而言之'proxy_set_header X-Authenticationfail $ sent_http_x_authenticationfail'在'/ login'位置 –

+0

只是去尝试,仍然没有运气, – James

+0

另外把'$ auth_request_set $ falure_reason sent_http_x_authenticationfail;''下面权auth_request'。你甚至不必在任何地方使用'$ falure_reason'。不知何故,这条线的存在将使我的第一个解决方案工作 –

回答

1

从你的描述,该任务是从在一个位置auth_request响应保存的报头,然后再通过此标头到下一个上游在另一个位置。

来自任何响应的头可以通过$sent_http_<header name>变量内达到进行请求的位置。这里的问题是Nginx的内存效率非常高。如果您以某种方式设法逃离某个位置,即进行内部重定向,Nginx会决定您将要发出另一个请求,提供静态文件或执行其他操作。因此,来自先前请求的任何数据现在被认为是不相关的,并且为了释放一些内存而被解雇。换句话说,$sent_http_<header name>变量会附加到一个位置,并且只要您离开该位置,它们就会停止工作。

但是,通过使另一个引用的内存持有的权益的价值的区域保持一些变量的一种方式。这是可能的,因为如前所述,Nginx具有内存效率。如果您为另一个变量的值赋予一个变量,那么Web服务器将不会复制源变量的值,除非真的有必要。相反,它将设置新变量的内部指针与内存中的地址,源变量的值保留在此处。

因此,如果您分配一个新的变量与$sent_http_<header name>的值,就会出现到响应的标题存储的内存区域的两个引用。你的新变量将保持这部分内存不被擦除,因为与大多数只在特定位置工作的内置变量不同,用户定义的变量会附加到服务器上下文中。

因此,为了解决您的问题,您需要定义一个新变量并赋值为$sent_http_x_authenticationfail

第一个明显的选择是使用set指令。但它不起作用,因为set在请求处理的非常早期阶段被调用,在发送任何请求并收到任何响应之前。

幸运的是,在Nginx中有一个特殊的指令,它可以完全实现这一点 - 分配一个新变量,结果为auth_request。而这个指令是auth_request_set。它proxy_set_header结合你会得到你想要的东西:

location/{ 
    auth_request /auth-proxy; 

    # Step 1: force Nginx to preserve the response header 
    auth_request_set $falure_reason $sent_http_x_authenticationfail; 

    error_page 401 =200 /login; 
    proxy_pass http://backend/; 
} 

location /login { 
    proxy_pass http://backend/login; 
    proxy_set_header X-Target $request_uri; 

    # Step 2: pass the preserved header value to the next upstream 
    proxy_set_header X-Authenticationfail $sent_http_x_authenticationfail; 
} 

location = /auth-proxy { 
    internal; 
    proxy_pass http://127.0.0.1:8888; 
} 

注意,因为这两个$falure_reason$sent_http_x_authenticationfail现在都指向相同的内存区,你可以在你login位置具有相同的结果使用这些变量。