2013-07-17 73 views
2

我對這個問題非常失望,我不知道問題出在哪裏,所以我希望你能幫助我。Varnish和ESI HTTP AUTH

我有一個symfony的HTTP BASIC認證,我試圖達到一個受此認證保護的URL,在Drupal頁面中有一個標籤。每個請求被髮送到光油

我給的用戶名和密碼的網址這樣的:

<esi:include src="http://admin:[email protected]:8081/app.php/next"/> 

在我的清漆的配置文件,我只有對於auth.http行:

if (req.http.Authorization) { 
    return (pass); 
} 

Symfony的後端在沒有http認證的情況下運行良好,並且當沒有Varnish和esi標籤時,http認證運行良好。

如果任何人有這個問題的想法,請告訴我,即使它是錯=)

回答

4

ESI清漆不一樣的iframe或鏈接標籤在工作中的一個瀏覽器,它不連接到您提供的任何網址。 ESI只是在清漆內啓動一個新的請求,並通過工作流程(vcl_recv等)。

你期望varnish的行爲像一個http客戶端,解析url,設置授權頭,設置一個主機頭爲api.dev:8081並啓動一個新的http連接/請求,它不會。在這種情況下,我猜想它會啓動一個新的req,將req.url設置爲/app.php/next,繼承父資源(包含esi標記)的請求中的標頭,或者可能完全忽略esi標記。

來完成你想做的事情的方式是(在vcl_recv):

if (req.esi_level > 0 && req.url == "/app.php/next") { 
    set req.http.Authorization = "BASIC [base64 encoded admin:adminpass]" 
    return (pass); 
} 

然後ESI標記看起來應該<esi:include src="/app.php/next" />

如果您需要ESI要求打一個不同的後端服務器,則需要到該服務器添加爲不同的命名後端:

backend authorization_needed { 
    .host = "api.dev"; 
    .port = "8081"; 
} 

和vcl_recv,告訴清漆用它來ESI要求:

if (req.esi_level > 0 && req.url == "/app.php/next") { 
    set req.http.Authorization = "BASIC [base64 encoded admin:adminpass]" 
    set req.backend = authorization_needed; 
    return (pass); 
} 

您可能還需要設置req.http.Host,如果後端響應的虛擬主機不是「api.dev」則阻止。

更新:

由於基本授權從客戶端來了,你在呼喚回報(通)時req.http.Authorization存在,清漆不會ESI過程的頁面。您必須在vcl_fetch()中明確啓用esi,而通過時不會調用它。

所以要通過授權的ESI片段而不是父頁面,改變vcl_rev:

if (req.http.Authorization && req.esi_level == 0) { 
    set req.http.X-Esi-Authorization = req.http.Authorization; 
    unset req.http.Authorization; 
} 
else if (req.http.X-Esi-Authorization && req.esi_level > 0) { 
    set req.http.Authorization = req.http.X-Esi-Authorization; 
    return (pass); 
} 

,並加入到vcl_fetch:

if (req.http.X-Esi-Authorization) { 
    set beresp.do_esi = true; 
} 

的淨效應是父母響應可緩存並將處理esi,esi片段本身將始終通過客戶端的授權標頭傳遞到後端。

+0

你好,謝謝你的回答。如果我試圖在標記中這樣做,那是因爲用戶和密碼會有_many_用戶和密碼用於同一個URL。所以,我不能直接在Varnish的conf中設置它。那麼,你認爲不可能做到這一點? – Peekmo

+0

這是一個非常典型的用例。我已經更新了答案。 –

+0

非常感謝!有用 ! – Peekmo