CakePHP - 由于安全组件,控制器测试失败

时间:2015-06-06 08:45:50

标签: security unit-testing cakephp cakephp-3.0

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

ContactsController

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()在浏览器中运行良好。

2 个答案:

答案 0 :(得分:3)

这是可以预期的,因为您没有发送必要的安全令牌,这是安全组件所需要的。

只需查看生成的表单,它将包含_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

答案 1 :(得分:0)

从Cake 3.1.2起,最好的方法是添加

person?.getName()?.firstName ?: "None"

到您的TestFunction。

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