cakephp 缺少Csrf标记Cookie

hyrbngr7  于 2022-11-11  发布在  PHP
关注(0)|答案(1)|浏览(194)

我对CakePHP(v3.7)比较陌生,我有一个应用程序,在其中我得到了一个“丢失Csrf令牌Cookie”的错误。
在Application.php中,我有:

$options = [];        // I'm fine with the default options.
$csrf = new CsrfProtectionMiddleware($options);
$middlewareQueue->add($csrf);

表单页面有一个隐藏的表单元素,其中有 _csrfToken。我很困惑为什么在POST上找不到它?
通过进一步研究,我发现在 CsrfProtectionMiddleware.php 中,下面的 _validateToken() 函数的行为如下:

  • $cookie * 为 null(未设置cookie)。因此,$cookienull
  • $post* 实际上包含页面上隐藏参数中的 _csrfToken 参数的内容。但是函数从不查看它。因为 $cookie 为空值,所以 if(!$cookie) 语句会引发 InvalidCsrfTokenException
protected function _validateToken(ServerRequest $request)
    {
        $cookies = $request->getCookieParams();
        $cookie = Hash::get($cookies, $this->_config['cookieName']);
        $post = Hash::get($request->getParsedBody(), $this->_config['field']);
        $header = $request->getHeaderLine('X-CSRF-Token');

        if (!$cookie) {
            throw new InvalidCsrfTokenException(__d('cake', 'Missing CSRF token cookie'));
        }

        if (!Security::constantEquals($post, $cookie) && !Security::constantEquals($header, $cookie)) {
            throw new InvalidCsrfTokenException(__d('cake', 'CSRF token mismatch.'));
        }
    }
}

显然,中间件除了一个隐藏参数之外,还期望一个 actual cookie。
更新:
我在浏览器端检查了一下。cookie正在被设置,但是浏览器在POST请求时没有返回它。
下面是CakePHP对原始GET请求的响应,以填充页面:

Connection: Keep-Alive
Content-Length: 3013
Content-Type: text/html; charset=UTF-8
Date: Wed, 08 May 2019 23:07:31 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.4.33 (Unix) PHP/7.1.1
Set-Cookie: csrfToken=b553dd2e06e57f6d514ee41a120e1c60084adafddfbaa6f72db1f7f590fcf50143876ac817d29d6f1cf9a786031d6235ba21e265b9d3b2a0ee4535854f048b66; path=/webroot/
X-Powered-By: PHP/7.1.1

请注意csrfToken cookie......下面是浏览器与表单数据一起发回的POST

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 184
Content-Type: application/x-www-form-urlencoded
DNT: 1
Host:*************
Origin:****************
Pragma: no-cache
Referer:***************
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36

查询字符串参数

redirect: /Users/login

表单数据

_method: POST
_csrfToken:  b553dd2e06e57f6d514ee41a120e1c60084adafddfbaa6f72db1f7f590fcf50143876ac817d29d6f1cf9a786031d6235ba21e265b9d3b2a0ee4535854f048b66
username: xxxxxxxxxx
password: xxxxxxxxxx

请注意,它返回的是隐藏的表单参数 _csrfToken,而不是cookie。
谢谢你的帮助...

suzh9iv8

suzh9iv81#

这是Apache中DOCUMENT_ROOT目录设置的问题,它被设置为webroot的父目录,而不是webroot本身,当我改变它时,一切都正常。

相关问题