2016-12-15 145 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位置具有相同的結果使用這些變量。