7

我在我的项目中使用安全组件,有什么方法可以在开发过程中获取有关错误的详细描述?例如:- 如果在不使用 cakephp 的 form 方法的情况下在视图中添加了任何字段,它会在我的 blackHoleCallback 函数中返回错误为“auth”。相反,我需要因为它返回该错误的原因。因为解决问题需要很多时间。有没有办法获得详细的错误描述?

4

4 回答 4

6

你所要做的就是找对地方

检查你的app/tmp/logs/error.log文件

如果您查看错误日志,您将看到如下条目:

2013-03-16 17:24:29 Error: [BadRequestException] The request has been black-holed
#0 root/lib/Cake/Controller/Component/SecurityComponent.php(228): SecurityComponent->blackHole(Object(FacebookUsersController), 'csrf')
#1 [internal function]: SecurityComponent->startup(Object(FacebookUsersController))
#2 root/lib/Cake/Utility/ObjectCollection.php(130): call_user_func_array(Array, Array)
#3 [internal function]: ObjectCollection->trigger(Object(CakeEvent))
#4 root/lib/Cake/Event/CakeEventManager.php(246): call_user_func(Array, Object(CakeEvent))
#5 root/lib/Cake/Controller/Controller.php(670): CakeEventManager->dispatch(Object(CakeEvent))
#6 root/lib/Cake/Routing/Dispatcher.php(183): Controller->startupProcess()
#7 root/lib/Cake/Routing/Dispatcher.php(161): Dispatcher->_invoke(Object(FacebookUsersController), Object(CakeRequest), Object(CakeResponse))
#8 root/app/webroot/index.php(96): Dispatcher->dispatch(Object(CakeRequest), Object(CakeResponse))
#9 {main}

阅读屏幕上的错误

如果您处于调试模式,则此错误也会在错误发生时显示在屏幕上。例如:

The request has been black-holed
Error: The requested address '/admin/fooby/edit/1' was not found on this server.

Stack Trace
CORE/Cake/Controller/Component/SecurityComponent.php line 228 → SecurityComponent->blackHole(FacebookUsersController, string)
[internal function] → SecurityComponent->startup(FacebookUsersController)
CORE/Cake/Utility/ObjectCollection.php line 130 → call_user_func_array(array, array)
[internal function] → ObjectCollection->trigger(CakeEvent)
CORE/Cake/Event/CakeEventManager.php line 246 → call_user_func(array, CakeEvent)
CORE/Cake/Controller/Controller.php line 670 → CakeEventManager->dispatch(CakeEvent)
CORE/Cake/Routing/Dispatcher.php line 183 → Controller->startupProcess()
CORE/Cake/Routing/Dispatcher.php line 161 → Dispatcher->_invoke(FacebookUsersController, CakeRequest, CakeResponse)
APP/webroot/index.php line 96 → Dispatcher->dispatch(CakeRequest, CakeResponse)

处理 csrf 错误

有了特定错误的详细信息(即您发布的数据,以及您当时会话中的确切令牌数据),就可以回答给您带来的问题,如果没有的话:

查看抛出错误的行。

在上面的堆栈跟踪中,错误来自CORE/Cake/Controller/Component/SecurityComponent.php line 228- 打开文件并查看该代码是什么:

if ($isPost && $isNotRequestAction && $this->csrfCheck) {
    if ($this->_validateCsrf($controller) === false) {
        return $this->blackHole($controller, 'csrf');
    }   
}

从中应该很明显的是,该函数_validateCsrf负责请求被黑洞。这应该不足为奇。

查看该函数的来源:

protected function _validateCsrf(Controller $controller) {
    $token = $this->Session->read('_Token');
    $requestToken = $controller->request->data('_Token.key');
    if (isset($token['csrfTokens'][$requestToken]) && $token['csrfTokens'][$requestToken] >= time()) {
        if ($this->csrfUseOnce) {
            $this->Session->delete('_Token.csrfTokens.' . $requestToken);
        }
        return true;
    }
    return false;
}

根据该函数返回 false 的原因,确定您如何继续调试。

正确配置组件

调试 CSRF 错误的必然结果是您需要修改Security 组件的配置

例如,您是否想要重用令牌,因为您的应用在页面加载之间多次提交相同的表单?

您是否通过向表单数据添加新字段来使表单请求自我失效 - 您可以使用unlockedFields 属性从 csrf 检查中排除这些字段。

您也可以完全禁用 CSRF 检查。这会带来明显的安全后果 - 但如果您正在努力使用该组件,这是一种解决您当前面临的问题的简单方法。

于 2013-03-16T16:50:06.930 回答
3

为了了解我在代码中挖掘的机制,以了解 FormHelper 哈希是如何创建的,以及 SecurityComponent 验证如何检查哈希。以下是如何准确了解幕后发生的事情。

检查 FormHelper 的输入。 打开 CORE/Cake/View/Helper/FormHelper.php。在 secure() 函数中,在 $files=Security::hash 行周围添加一些 pr 行,以查看令牌是如何构建的:

pr($fields);//hashed into computed token on next line
$fields = Security::hash(serialize($fields) . $unlocked . Configure::read('Security.salt'), 'sha1');
pr($unlocked); //hashed into computed token
pr(Configure::read('Security.salt')); //hashed into computed token
pr($fields); //computed token passed via hidden token field in form

检查表单是如何处理 的 现在检查提交的表单是如何处理的,并与传递的令牌进行比较:打开 CORE/Cake/Controller/Component/SecurityComponent.php。在最后的 _validatePost() 例程中插入一些 pr 行:

pr($fieldList); //hashed into computed token
pr($unlocked); //hashed into computed token
pr(Configure::read('Security.salt')); //hashed into computed token
pr($token); //passed token from FormHelper
pr($check); //computed token

希望这可以帮助其他遇到锁定/解锁或丢失字段问题的人快速弄清楚蛋糕内部发生了什么。

于 2013-08-27T01:57:50.983 回答
1

还请记住,您必须在由 theToken生成的FormHelper和使用 Session 检索到的 bu cake 之间完全匹配。正如文档所说,当您动态生成输入或进行 ajax 调用时,可能会发生不匹配:记住序列化表单并通过 ajax 提交!

如果您生成的输入标签不是使用 生成的FormHelper,则必须解锁它们。例如在你的beforeFilter()

$this->Security->unlockedFields = 
                 array('MyModel.some_field1','MyModel.some_field2')

wherefield1field2是“手动”生成的字段,即不使用 Helper。

于 2014-02-20T14:59:14.867 回答
1

回答这个问题:“有没有办法获得详细的错误描述?”

当涉及到 SecurityComponent 时,第一件事是为您的控制器添加更有价值的调试。这是一种方法:

public function beforeFilter() {
    parent::beforeFilter();

    //your beforeFilter code

    //Enable CSRF and other protections
    $this->Security->csrfExpires = '+1 hour';
    $this->Security->csrfUseOnce = true;
    $this->Security->blackHoleCallback = 'blackhole';
}

public function blackhole($errorType) {

    $errorMap['auth']   = 'form validation error, or a controller/action mismatch error.';
    $errorMap['csrf']   = 'CSRF error.';
    $errorMap['get']    = 'HTTP method restriction failure.';
    $errorMap['post']   = $errorMap['get'];
    $errorMap['put']    = $errorMap['get'];
    $errorMap['delete'] = $errorMap['get'];
    $errorMap['secure'] = 'SSL method restriction failure.';
    $errorMap['myMoreValuableErrorType']    = 'My custom and very ' . 
    'specific reason for the error type.';

    CakeLog::notice("Request to the '{$this->request->params['action']}' " . 
"endpoint was blackholed by SecurityComponent due to a {$errorMap[$errorType]}");
}

正如 AD7six 提到的,看看CORE/Cake/Controller/Component/SecurityComponent.php. 具体来说SecurityComponent::startup()。在该方法中,您会注意到该SecurityComponent::blackhole()方法运行了几次。只要条件未能通过安全检查,它就会运行,如下所示:

return $this->blackHole($controller, 'auth');

在这种情况下,“auth”表示失败的安全检查类型。您可以自定义 'auth' 字符串以使其更有价值。例如,使用“myMoreValuableErrorType”代替“auth”,然后将其映射到更有意义的东西。

因此,不是$this->blackHole($controller, 'auth')在安全检查失败时运行,而是运行$this->blackHole($controller, 'myMoreValuableErrorType'),然后使用上面的代码将“myMoreValuableErrorType”映射到失败的具体原因。

于 2015-09-03T04:15:42.973 回答