我对这个问题很遗憾,我不知道问题出在哪里,所以,我希望你能帮助我。
我有一个使用symfony的HTTP BASIC身份验证,我正在尝试访问受此身份验证保护的URL,并在Drupal页面中添加一个标记。每个请求都发送到一个Varnish
我在网址中输入用户名和密码:
<esi:include src="http://admin:adminpass@api.dev:8081/app.php/next"/>
在我的清漆配置文件中,我只有auth.http:
的那些行if (req.http.Authorization) {
return (pass);
}
我的Symfony后端在没有http身份验证的情况下运行良好,并且当没有Varnish和esi标签时,http身份验证效果很好。
如果有人知道这个问题,请告诉我,即使它是错的=)
答案 0 :(得分:4)
var in中的ESI不像浏览器中的iframe或链接标记,因为它不会连接到您提供的任何URL。 ESI只是在varnish中启动一个新请求并完成工作流程(vcl_recv等)。
你期望varnish像http客户端一样,解析url,设置授权头,将主机头设置为api.dev:8081并启动一个新的http连接/请求,它不会。在这种情况下,我的猜测是它开始一个新的req,req.url设置为/app.php/next继承父资源请求(包含esi标签)的头文件,或者可能只是完全忽略esi标签。 / p>
完成你想要做的事情的方法是(在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中,告诉varnish将其用于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);
}
如果后端响应不同于“api.dev”的虚拟主机,则可能还需要设置req.http.Host。
更新:
由于基本授权来自客户端,并且在req.http.Authorization存在时调用return(pass),因此varnish不会对这些页面进行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片段本身将始终使用客户端的授权头传递给后端。