如何解决NextCloud CSRF check failed?

Cloud storage

1 前言

一个问题,一篇文章,一出故事。
用户访问一个分享的链接并输入校验密码,
https://nextcloud.cmdschool.org/index.php/s/4enSiaFR8NkSDwj
浏览器有如下错误提示,

csrf check failed

注:用户反馈使用Edg浏览器会不定时出现错误提示且更换Google Chrome浏览器后可正常使用。

2 最佳实践

2.1 查看服务器日志

tail -f /var/log/nextcloud/nextcloud.log

服务器日志可见如下错误提示,

{"reqId":"YaoGLmDx86fzQUBJ03LO","level":2,"time":"2022-08-29T08:26:04+08:00","remoteAddr":"10.168.0.93","user":"--","app":"core","method":"GET","url":"/index.php/s/4enSiaFR8NkSDwj","message":"Renewing session token failed","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.81 Safari/537.36 Edg/104.0.1293.47","version":"23.0.2.1"}

2.2 定位报错的代码

cd /var/www/nextcloud/
grep -R "Renewing session token failed"

得到如下提示,

lib/private/User/Session.php:                   \OC::$server->getLogger()->warning('Renewing session token failed', ['app' => 'core']);

2.3 分析源代码并解决问题

vim /var/www/nextcloud/lib/private/User/Session.php

可见如下代码,

        /**
         * perform login using the magic cookie (remember login)
         *
         * @param string $uid the username
         * @param string $currentToken
         * @param string $oldSessionId
         * @return bool
         */
        public function loginWithCookie($uid, $currentToken, $oldSessionId) {
                $this->session->regenerateId();
                $this->manager->emit('\OC\User', 'preRememberedLogin', [$uid]);
                $user = $this->manager->get($uid);
                if (is_null($user)) {
                        // user does not exist
                        return false;
                }

                // get stored tokens
                $tokens = $this->config->getUserKeys($uid, 'login_token');
                // test cookies token against stored tokens
                if (!in_array($currentToken, $tokens, true)) {
                        return false;
                }
                // replace successfully used token with a new one
                $this->config->deleteUserValue($uid, 'login_token', $currentToken);
                $newToken = $this->random->generate(32);
                $this->config->setUserValue($uid, 'login_token', $newToken, $this->timeFactory->getTime());

                try {
                        $sessionId = $this->session->getId();
                        $token = $this->tokenProvider->renewSessionToken($oldSessionId, $sessionId);
                } catch (SessionNotAvailableException $ex) {
                        return false;
                } catch (InvalidTokenException $ex) {
                        \OC::$server->getLogger()->warning('Renewing session token failed', ['app' => 'core']);
                        return false;
                }

从上面代码笔者分析程序通过Cookie获取的一个Token,于是笔者尝试禁用浏览器的Cookie,于是可以重现“csrf check failed”的错误提示。
回想用户反馈用户反馈使用Edg浏览器会不定时出现错误提示且更换Google Chrome浏览器后可正常使用,于是笔者让PC管理员升级浏览器后再观察后面是否会再次出现错误提示。

参阅文档
================
https://github.com/nextcloud/server/issues/26502

没有评论

发表回复

Cloud storage
如何部署基于Nginx部署NextCloud?

1 前言 一个问题,一篇文章,一出故事。 以往使用LAMP环境部署的NextCloud已经工作良久, …

Cloud storage
如何修复NextCloud通讯录图片损坏问题?

1 前言 一个问题,一篇文章,一出故事。 笔者最近需要测试升级NextCloud,发现通讯录显示损坏 …

Cloud storage
如何迁移NextCloud数据目录?

1 前言 一个问题,一篇文章,一出故事。 笔者需要迁移NextCloud的默认数据目录“/var/w …