2013-07-17 37 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