如何使用Varnish缓存RESTful API,但仍然使用HMAC签名/验证每个请求?

时间:2014-02-19 20:06:28

标签: api rest caching varnish hmac

我有兴趣使用Varnish缓存/限制/等响应我正在创建的RESTful API。我可能过于松散地使用术语/首字母缩略词“HMAC”,但我的意思是每个对我的API的请求都应该包含一个标题,该标题包含客户端通过散列部分请求(包括时间戳)计算的哈希值共享秘密。然后,服务器使用来自请求的相同成分计算此相同的散列,并确定请求是否有效并应响应。

这很好用,但现在我想使用Varnish来缓存我的API响应。 HMAC的性质要求每个请求计算哈希以验证用户是谁,但返回的实际响应是相同的 - 因此API调用的内容非常容易缓存。

我想要的(我假设这可以实现,我只是不知道如何)是将身份验证任务传递给后端,以某种方式告诉Varnish“是的,继续并回应此请求“或”否,不响应此请求“然后从那里让Varnish确定是否可以从缓存中提供请求。

更理想的情况是,做一些稍微更漂亮的事情,让Varnish自己处理身份验证,或者将HMAC处理传递给比后端更快的东西。例如,API可能将客户端密钥/公钥存储在redis缓存中,然后Varnish可能实际使用Redis中的值计算哈希本身。

2 个答案:

答案 0 :(得分:3)

您应该能够使用两个VCL在Varnish Varnish Modules代码(清漆配置语言)中实现更高级的解决方案:

两个模块都在生产中使用,如modules directory

中所列

如果Varnish在VCL中处理身份验证,您可以让Varnish缓存您的API后端响应,并仅为经过身份验证的请求提供响应。

如果HMAC实施需要请求正文:

作为Gridfire points out在他/她的回答中,Varnish无法访问请求正文。我们可以/不应该从后端/应用程序的HTTP头中发送完整的请求主体。

但是,我们可以在HTTP标头中发送完整请求正文的散列/摘要。与生成输出(标记|数据|无论什么)相比,后端的散列计算应该可以忽略不计。 AFAICT只要哈希/摘要和HMAC是健壮的,并且摘要很长(256位或更多),那么该方法应该没有密码/实际缺点。通常会进行性能测试。

答案 1 :(得分:0)

Varnish可以使用Geir Bostad答案中的VMOD轻松完成HMAC,除非您的HMAC实现使用请求主体作为哈希的一部分。 Varnish不允许您访问请求正文,libvmod-bodyaccess提供了一些功能,但我找不到实际获取请求正文的方法。

理论上你可以添加一个包含请求体的标头,但这是非常糟糕的做法,如果您选择仅将数据放入标头中,则会使用冗余数据膨胀您的HTTP请求,或者破坏HTTP请求标准。简单地说不推荐。

另一种解决方案是使用Nginx,如果你想使用HTTPS(Varnish不做SSL),它也可以作为SSL终止符。 Nginx有module来运行Lua脚本(Ubuntu / Debian包nginx-extras提供它而不需要你自己编译),模块带来了方便的access_by_lua_file指令允许或阻止访问基于脚本的结果。 Nginx here有一个HMAC脚本。