【问题标题】:CakePHP - Controller testing failed because of Security componentCakePHP - 由于安全组件,控制器测试失败
【发布时间】:2015-06-06 08:45:50
【问题描述】:

我正在尝试测试使用安全组件的控制器方法(添加、编辑……)。

联系人控制器

public function initialize() {
    $this->loadComponent('Security');
}

public function add() {
    $contact = $this->Contacts->newEntity();
    if ($this->request->is('post')) {
        $contact = $this->Contacts->patchEntity($contact, $this->request->data);
        if ($this->Contacts->save($contact)) {
            $this->Flash->success(__d('contact_manager', 'The contact has been saved.'));
            return $this->redirect(['action' => 'index']);
        } else {
            $this->Flash->error(__d('contact_manager', 'The contact could not be saved. Please, try again.'));
        }
    }
    $this->set(compact('contact'));
    $this->set('_serialize', ['contact']);
}

ContactsControllerTest

public function testAdd() {
    $data = $this->_getData();
    $this->post('/contacts/add', $data);
    $this->assertResponseSuccess();

    $query = $this->Contacts->find()->where([
        'Profiles.lastname' => $data['profile']['lastname'],
        'Profiles.firstname' => $data['profile']['firstname']
    ]);
    $this->assertEquals(1, $query->count());
}

protected function _getData() {
    $data = [
        'id' => '',
        'organization_id' => 2,
        'profile_id' => '',
        'profile' => [
            'lastname' => 'Demo',
            'firstname' => 'Demo',
            'gender' => 'f',
            'birthday' => '1990-05-20',
            'email' => 'demo@demo.com',
            'phone' => '0102030405',
            'phone_mobile' => '0607080900'
        ]
    ];
    return $data;
}

testAdd() 总是失败,因为请求是黑洞的(带有 'Auth' 指示符),但 add() 在浏览器中运行良好。

【问题讨论】:

    标签: security unit-testing cakephp cakephp-3.0


    【解决方案1】:

    这是意料之中的,因为您没有发送必要的安全令牌,而这是安全组件所需要的。

    看看您生成的表单,它将包含 _Token 字段的隐藏输入,以及子键 fieldsunlocked,其中 fields 将包含一个哈希值,并且可能包含锁定字段的名称,并且unlocked 保存未锁定字段的名称。

    只需将令牌数据添加到您的请求中,一切都会好起来的。这是一个例子

    $data = [
        'id' => '',
        'organization_id' => 2,
        'profile_id' => '',
        'profile' => [
            'lastname' => 'Demo',
            // ...
        ],
        '_Token' => [
            'fields' => 'e87e3ad9579abcd289ccec2a7a42065b338cacd0%3Aid'
            'unlocked' => ''
        ]
    ];
    

    注意unlocked必须存在,即使它不包含任何数据!

    您应该能够简单地从生成的表单中复制令牌值,如果您对令牌的生成和验证方式感兴趣,请查看 FormHelper::secure()FormHelper::_secure()SecurityComponent::_validatePost()

    另请参阅Cookbook > Controllers > Components > Security

    【讨论】:

    • 我在$data 中添加了带有子键的_Token 字段,因此$data 包含与生成的表单完全相同的键。但是testAdd() 再次失败(带有“auth”黑洞)。
    • @Lacos 然后我建议您进行一些调试,将自己侵入安全组件,检查它到底在哪里退出,它检索到什么值,生成的比较哈希与一个你的过去,等等......我真的无能为力。
    • 非常感谢。我的测试总是因为用于生成令牌的当前请求 URL 而失败。如果我在控制台 (/contacts/add) 中启动测试并且在浏览器中使用表单 (/myapp/contacts/add),则此 url 不一样。
    【解决方案2】:

    从 Cake 3.1.2 开始最好的方法是添加

    $this->enableCsrfToken();
    $this->enableSecurityToken();
    

    到您的 TestFunction。

    独库:https://book.cakephp.org/3.0/en/development/testing.html#testing-actions-protected-by-csrfcomponent-or-securitycomponent

    【讨论】:

    • 我得到 _Token is not found in request data,这解决了它。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-03
    • 1970-01-01
    • 2013-12-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多