有什么方法可以在清漆中使用 auth headers 缓存请求

Is there any way to cache request with auth headers in varnish

有什么方法可以在 varnish 中缓存带有 auth headers 的请求吗? 我想在缓存请求时忽略身份验证 headers

这是完全可能的,但也非常危险:Varnish 会对所有请求return 相同的缓存(授权)内容。

示例:

用户 A 通过适当的身份验证请求资源 Z。 Varnish 将请求中继到后端,缓存响应和 returns 资源。

用户 B 通过适当的身份验证请求资源 Z。他们将获得缓存资源 Z 即使 Z 包含用户 A 的内容.

用户 X 使用 无效身份验证 请求资源 Z。由于后端被绕过,他们无论如何也将获得缓存资源。


话虽如此,您可以覆盖 Varnish 的 built-in VCL。详细信息 documented 但主要思想是:

source 复制默认 vcl_recv VCL(适用于您的版本)并将其添加到 vcl_recv.

的末尾

vcl_recv 中删除保护措施:只需删除禁用缓存的 vcl_req_authorization

sub vcl_req_authorization {
    if (req.http.Authorization) {
        # Not cacheable by default.
        return (pass);
    }
}

在您的 vcl 文件中,在末尾发出一个 return 语句,这样 built-in vcl 就不会被使用。

有多种方法可以解决这个问题,具体取决于身份验证 headers 的重要性。

1。你不关心 auth

如果您不关心授权部分,并且想冒着向未授权用户提供缓存内容的风险,您可以使用以下 VCL 代码:

sub vcl_recv {
    unset req.http.Authorization;
}

2。某种程度上忽略授权

稍微在意auth也是可以的,但不要太在意

以下 VCL 片段将允许缓存,即使存在 Authorization header:

sub vcl_recv {
    if(req.http.Authorization) {
        return(hash);
    }
}

这样做的结果是初始缓存未命中将传递到后端并在那里进行处理。将在那里处理潜在的未经授权的访问。

但是一旦处理完毕,object 就会存储在缓存中,无论该请求的授权状态如何,下一个请求都将获得缓存的内容。

3。在边缘执行身份验证

也可以在缓存内容的同时在 Varnish 中处理 auth 部分。

以下 VCL 代码将处理此问题:

sub vcl_recv {
    if(req.http.Authorization != "Basic YWRtaW46c2VjcmV0") {
        return (synth(401, "Restricted"));
    }
    unset req.http.Authorization; 
}

sub vcl_synth {
    if (resp.status == 401) {
        set resp.http.WWW-Authenticate = {"Basic realm="Restricted area""};
    }
}

此代码将主动检查 Authorization header 的内容,并确保使用用户名 admin 和密码 secret

YWRtaW46c2VjcmV0字符串只不过是admin:secret.

的base64编码

4。使用 vmod_basicauth

一种更高级、更灵活的终止边缘身份验证的方法是使用 https://git.gnu.org.ua/vmod-basicauth.git/. This VMOD can be compiled from source and can be downloaded from ftp://download.gnu.org.ua/release/vmod-basicauth.

假设凭据存储在 /var/www/.htpasswd 中,您可以利用此 VMOD 将 Authorization header 与 .htpasswd 文件的内容相匹配。

这是 VCL:

vcl 4.1;

import basicauth;

sub vcl_recv {
    if (!basicauth.match("/var/www/.htpasswd",req.http.Authorization)) {
        return (synth(401, "Restricted"));
    }
    unset req.http.Authorization;
}

sub vcl_synth {
    if (resp.status == 401) {
        set resp.http.WWW-Authenticate = {"Basic realm="Restricted area""};
    }
}