Codeigniter 3 系统 - 启用 CSRF 保护会导致致命错误 CI_Controller not found

Codeigniter 3 system - enabling CSRF protection causes a fatal error CI_Controller not found

提问人:Kobus Myburgh 提问时间:10/6/2023 最后编辑:Kobus Myburgh 更新时间:11/21/2023 访问量:45

问:

我正在开发一个基于 CodeIgniter 3 的系统,并且有人要求在登录和注册表单上启用 CSRF。

在我的配置文件中,我完成了:

$config['csrf_protection'] = FALSE;
if (isset($_SERVER["REQUEST_URI"])) {
    if (stripos($_SERVER["REQUEST_URI"], '/login') !== FALSE || stripos($_SERVER["REQUEST_URI"], '/register') !== FALSE ) {
        $config['csrf_protection'] = TRUE;
    }
}

但是当我尝试将配置变量设置为 true 时,我的错误处理程序会触发函数不存在。这个函数确实存在于我的函数中,并且该错误具有误导性,因为它实际上抱怨没有首先找到这个函数,但实际的错误是应该没有找到,最初导致我相信 CodeIgniter 实例没有被识别,即使回溯表明不是这样:csrf_protectionMY_url_helperCI_Controller

Array
(
    [0] => Array
        (
            [file] => path\to\system\core\Exceptions.php
            [line] => 268
            [function] => include
        )

    [1] => Array
        (
            [file] => path\to\system\core\Common.php
            [line] => 627
            [function] => show_php_error
            [class] => CI_Exceptions
            [object] => CI_Exceptions Object
                (
                    [ob_level] => 1
                    [levels] => Array
                        (
                            [1] => Error
                            [2] => Warning
                            [4] => Parsing Error
                            [8] => Notice
                            [16] => Core Error
                            [32] => Core Warning
                            [64] => Compile Error
                            [128] => Compile Warning
                            [256] => User Error
                            [512] => User Warning
                            [1024] => User Notice
                            [2048] => Runtime Notice
                        )

                )

            [type] => ->
            [args] => Array
                (
                    [0] => Error
                    [1] => Uncaught Error: Class "CI_Controller" not found in path\to\system\core\CodeIgniter.php:369
Stack trace:
#0 path\to\app\core\MY_Exceptions.php(54): get_instance()
#1 path\to\system\core\Common.php(195): MY_Exceptions->__construct()
#2 path\to\system\core\Common.php(656): load_class('Exceptions', 'core')
#3 [internal function]: _exception_handler(Object(Error))
#4 {main}
thrown
                    [2] => core/CodeIgniter.php
                    [3] => 369
                )

        )

    [2] => Array
        (
            [file] => path\to\system\core\Common.php
            [line] => 693
            [function] => _error_handler
            [args] => Array
                (
                    [0] => 1
                    [1] => Uncaught Error: Class "CI_Controller" not found in path\to\system\core\CodeIgniter.php:369
Stack trace:
#0 path\to\app\core\MY_Exceptions.php(54): get_instance()
#1 path\to\system\core\Common.php(195): MY_Exceptions->__construct()
#2 path\to\system\core\Common.php(656): load_class('Exceptions', 'core')
#3 [internal function]: _exception_handler(Object(Error))
#4 {main}
thrown
                    [2] => path\to\system\core\CodeIgniter.php
                    [3] => 369
                )

        )

    [3] => Array
        (
            [function] => _shutdown_handler
            [args] => Array
                (
                )

        )

)

如果从我能看到的所有迹象来看,CodeIgniter 已加载,我对它如何不工作感到非常困惑。代码库扩展了 CI_Exceptions 类,这是我现在用于测试的构造函数:

class MY_Exceptions extends CI_Exceptions
{
    public function __construct() {
        parent::__construct();
        die('Error is showing');
        $this->CI =& get_instance();
        die('Error not showing');
    }
}

不知何故,当分配实例时,一切都变成了梨形。

这个问题:激活 CSRF 保护时出错提供了一些看起来相同的信息,但接受的答案并不是我可以实现的真正答案。

将我的 CI 错误日志记录设置为级别 4(所有消息)给我这个:

INFO - 2023-10-06 13:47:57 --> Config Class Initialized
INFO - 2023-10-06 13:47:57 --> Hooks Class Initialized
DEBUG - 2023-10-06 13:47:57 --> UTF-8 Support Enabled
INFO - 2023-10-06 13:47:57 --> Utf8 Class Initialized
INFO - 2023-10-06 13:47:57 --> URI Class Initialized
INFO - 2023-10-06 13:47:57 --> Router Class Initialized
INFO - 2023-10-06 13:47:57 --> Output Class Initialized
INFO - 2023-10-06 13:47:57 --> Security Class Initialized
DEBUG - 2023-10-06 13:47:57 --> Global POST, GET and COOKIE data sanitized

此日志中没有任何错误。

有什么想法吗?

PHP CodeIgniter 异常

评论

0赞 MTMDev 10/6/2023
这是这样的设置?stackoverflow.com/questions/76178617/......IMO 我从未使用过这个,我使用基于会话的 cookie,并且在执行任何用户配置文件操作之前始终检查用户是否有效并登录,否则他们会被重定向到登录页面。
0赞 Kobus Myburgh 10/7/2023
嗨,是的,就是这样,但有条件地启用,而不是为所有形式启用。您的其余评论不适用于我的情况。这不是关于重定向到适当的位置,而是关于防止跨站点请求伪造 (CSRF)。
0赞 MTMDev 10/12/2023
您可以通过在表单和用户会话 cookie 中创建隐藏令牌来滚动自己的反 CSRF。然后在提交时比较两者以匹配确定,并且仅在需要此安全性的表单上进行比较。我提到的重定向仅在检查失败时才出现。干杯。
1赞 Kobus Myburgh 11/21/2023
@MTMDev - 如果您遇到此问题,请参阅下面的答案 - 终于得到了一些工作,尽管不优雅,并打破了一些规则......

答:

0赞 Kobus Myburgh 11/21/2023 #1

我终于找到了一个非常不优雅的修复程序(也违背了最佳实践,但由于缺乏更好的解决方案,这将不得不这样做)。

CodeIgniter 3 CSRF/Security 实现似乎在初始化它需要满足请求的类之前调用了过程函数。它似乎发生在某种循环中,因为它只在第一次失败,然后所需的类似乎被初始化,第二次开始它工作。这是我能想到的最好的解释 - 可能完全偏离基础,但我的修复有效。get_instance()

注意::我知道不要更改系统的核心文件,并且我理解围绕它的逻辑,但这不是一个类。它是过程代码,所以不能扩展它。然后,我尝试调整和扩展引用的类,但这很快就变得混乱了 - 所以如果有人有更好的解决方案,我愿意接受建议。

从这里改变:system\core\CodeIgniter.php

function &get_instance()
{
    return CI_Controller::get_instance();
}

对此:

function &get_instance()
{
    if (class_exists('CI_Controller')) {
        return CI_Controller::get_instance();
    }
}

为我解决了问题,没有任何其他问题,CSRF 按预期工作。看起来好像第一次调用此方法时,类尚未初始化。回溯没有给我足够的信息来追踪这种情况的实际发生位置。get_instance()