索纳塔 CSRF 令牌无效,但形式正确

Sonata CSRF token invalid although form correct

在使用 Symfony/Sonata 时,我们面临 CSRF 令牌无效错误

以前,同样的代码可以完美运行。我们确保 令牌已通过表单正确发布。奇怪的是,该错误仅针对选定的实体出现。

浏览所有其他 Q/A 并不能解决问题。

如果客户端和服务器之间的一般通信正常,还有什么可以使 CSRF 令牌无效?

解法:php.ini中增加max_input_vars,至少要超过默认的1000:

max_input_vars=2000

原因: 我们在 nginx 日志中找到了导致 CSRF 令牌失败的原因。事实上,令牌失效只是一个普遍问题的症状。

以下三个错误日志条目可以解决问题:

  1. 实体请求的大小很大。这就是第一个错误发生的原因:“这意味着上传文件的大小大于为上传保留的 in-memory 缓冲区。” (参见 https://serverfault.com/a/511790)。事实上,Sonata 在一个实体对象中创建了很多 sub-objects。

*357395 a client request body is buffered to a temporary file /var/cache/nginx/client_temp/0000000742, client: 192.168.10.152, server: xxx request: "POST /admin/entity/1234/edit?uniqid=s588b2b142c3d2 HTTP/1.1", host: "xxxx", referrer: "http://xxx/admin/entity/1234/edit"

  1. 这是决定性的信息。 max_input_vars 定义了 $_POST 请求将接受多少输入变量。如果超过(默认)限制 1000,PHP 将截断 "further input variables [...] from the request"。因此,CSRF 令牌被 PHP 从 $_POST 变量中截断了。

error_admin: 2017/01/27 12:19:19 [error] 51723#51723: *357395 FastCGI sent in stderr: "PHP message: PHP Warning: Unknown: Input variables exceeded 1000. To increase the limit change max_input_vars in php.ini. in Unknown on line 0" while reading response header from upstream, client: 192.168.10.152, server: xxx, request: "POST /admin/entity/1234/edit?uniqid=s588b2b142c3d2 HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "xxx", referrer: "xxx/admin/entity/1234/edit"

  1. 这就是第三个错误发生的原因。 "Connection reset by peer while sending to client",因为 $_POST 请求中的 token 显然不存在(不再存在),因为它要么被完全切断,要么被切断。对等方未找到有效令牌,因此拒绝请求。

2017/01/27 12:19:19 [info] 51723#51723: *357395 recv() failed (104: Connection reset by peer) while sending to client, client: 192.168.10.152, server: xxx, request: "POST /admin/entity/1234/edit?uniqid=s588b2b142c3d2 HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "xxx", referrer: "xxx/admin/entity/1234/edit?uniqid=s588b2b142c3d2"