我有一个以 Varnish 服务器为前端的应用程序。页面的某些部分使用 ESI 包含项进行呈现。
我的问题是上游响应包含一个加密的会话 cookie,其中除其他外还包含一个 CSRF 令牌(根本没有服务器端会话存储)。
对于初始请求(请求中没有 cookie),ESI 请求将不包含上游服务器的第一个响应设置的 cookie。
我尝试设置req.http.Cookie
钩子vcl_deliver
,因为它是请求流中唯一可以同时进行读写访问的地方。但是,使用 varnishlog 查看请求发现 ESI 请求不受影响,req
并且res
不包含 cookie。
我已尽力仔细查阅文档,但没有找到任何有用的东西。
是否可以实现我想要的,即更新req
以便 ESI 请求包含初始上游响应返回的 cookie?
答案1
我们需要明确区分包含标头的请求Cookie
和包含标头的响应Set-Cookie
。
假设 CSRF 令牌是通过Set-Cookie
父响应的标头设置的,您可能希望通过Cookie
ESI 子请求中的请求标头访问该值。
假设 Cookie 标头已包含 CSRF 令牌
该req_top.http.Cookie
变量可以访问父请求的 cookie,但是req_top
无法在解析vcl_backend_response
ESI 占位符的地方访问。
您可以使用以下 VCL 代码片段绕过此限制:
sub vcl_recv {
if (req.esi_level > 0 ) {
set req.http.X-Parent-Cookie = req_top.http.Cookie;
}
}
这将启用通过X-Parent-Cookie
可用的标题。vcl_backend_response
bereq.http.X-Parent-Cookie
假设 Cookie 标头尚未包含 CSRF 令牌
可以现实地假设它req_top.http.Cookie
尚未包含 CSRF 令牌的值,因为在处理 ESI 子请求时,Cookie
客户端尚未设置标头。
我能想到的唯一解决方案是将父Set-Cookie
值存储在变量中。Varnish 本身不支持变量,需要官方https://github.com/varnish/varnish-modules待安装。
您必须从源代码进行编译。
看https://github.com/varnish/varnish-modules/blob/master/src/vmod_var.vcc获取vmod_var
API 和代码示例。