对包含了CSRF防护的表单页面进行缓存

3.4 版本
维护中的版本

CSRF tokens对每个用户来说都是不同的。这就是为什么在你尝试去缓存“包含了表单”的页面时,需要保持警惕的原因。

更多关于CSRF防护在Symfony中如何运作的信息,请参考 CSRF Protection

为什么在缓存“包含了CSRF token”的页面时是有问题的 

一般来说,每个用户都有一个CSRF token,被存于session中,用于验证。这意味着如果你缓存了一个页面,它包含有CSRF token,那么你缓存的只是第一个用户的那个CSRF token。当用户提交表单时,这个token不会匹配存在session中的token,则所有用户(除了第一个访问页面的)在提交表单时,将无法通过CSRF验证。

实际上,所有反向代理(如Vanish)都禁止缓存含有CSRF token的页面。这是因为为了保持PHP session的开启,有一个cookie会被发出,而Varnish的默认行为是不对含有cookie的HTTP请求进行缓存的。

如何缓存页面中的绝大部分,且仍能使用CSRF防护 

为了缓存一个含有CSRF token的页面,你要使用更加高级的缓存技巧,像是 ESI fragments,这时你可以缓存全页,并内嵌表单于ESI tag之内,令其根本不被缓存。

另一个办法,就是通过未被缓存的ajax请求来加载表单,仅去缓存HTML响应的其他部分。

或者你干脆通过一个Ajax请求来加载CSRF token,并用它来替换表单字段的值。

本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。

登录symfonychina 发表评论或留下问题(我们会尽量回复)