我想在动作中使用ajax帖子。 GET请求工作正常,但是当我尝试POST时,我在firebug中看到“400 Bad Request”,视图返回“Black hole”响应。
这是Jquery请求:
$.ajax({
url:"/usermgmt/users/editUser",
type:"POST",
success:function(data) {
alert('Wow this actually worked');
//ko.applyBindings(self);
},
error:function() {
alert('This will never work');
}
});
这是由于Cake的安全设置还是我在这里缺少什么?
答案 0 :(得分:18)
防止表单篡改是安全组件提供的基本功能之一。只要启用它,它就会将所有POST视为表单提交。
常规的手动编码HTML表单无法在启用安全组件的情况下使用,因此JQuery生成的POST也不会。当然,您可以使用$this->Security->validatePost = false;
或$this->Security->csrfCheck = false;
,但随后您将失去安全组件提供的保护。
要使安全组件保持正常运行,您需要使用CakePHP表单助手创建您将通过ajax发布的表单。这样,data[_Token][fields]
和data[_Token][unlocked]
隐藏字段就会生成其密钥:
<?php
echo $this->Form->create('Test',array('id'=>'testform'));
echo $this->Form->input('Something');
echo $this->Form->submit();
echo $this->Form->end();
?>
这将生成如下内容:
<form action="/your/url" id="testform" method="post" accept-charset="utf-8">
<div style="display:none;">
<input type="hidden" name="_method" value="POST"/>
<input type="hidden" name="data[_Token][key]" value="9704aa0281d8b5a2fcf628e9fe6f6c8410d8f07a" id="Token937294161"/>
</div>
<div class="input text">
<input name="data[Test][Something]" class="required" type="text" id="TestSomething"/>
</div>
<div class="submit">
<input type="submit" />
</div>
<div style="display:none;">
<input type="hidden" name="data[_Token][fields]" value="0c81fda1883cf8f8b8ab39eb15d355eabcfee7a9%3A" id="TokenFields817327064"/>
<input type="hidden" name="data[_Token][unlocked]" value="" id="TokenUnlocked281911782"/>
</div>
</form>
现在只需要在JQuery中序列化这个表单,以便可以使用ajax POST发送它:
$('#testform').submit(function(event) {
$.ajax({
type: 'POST',
url: "/your/url",
data: $('#testform').serialize(),
success: function(data){
alert('Wow this actually worked');
},
error:function() {
alert('This will never work');
}
});
event.preventDefault(); // Stops form being submitted in traditional way
});
现在,如果您按下提交按钮,POST将会成功。
重要事项:由于表单助手的令牌只能与安全组件一起使用,因此只有每打算生成一次POST时,此解决方案才有效。如果您需要能够在页面重新加载之间多次发布相同的表单,那么当您在Controller的开头添加安全组件时,您需要执行以下操作:
public $components = array(
'Security' => array(
'csrfUseOnce' => false
)
);
...这将允许令牌用于多个请求。它不是 安全,但您可以将其与csrfExpires
结合使用,以便令牌最终到期。这些都记录在CSRF configuration section of the Cake book。
答案 1 :(得分:2)
仅供参考,CakePHP 2.3及更高版本现在包含unlockedActions,仅用于在控制器或AppController中的beforeFilter中使用。
$this->Security->unlockedActions = array('ajaxAction');
答案 2 :(得分:0)
让shure你将函数editUser放在:
public function beforeFilter(){
parent::beforeFilter()
$this->Auth->allow('editUser');
}
在UsersController内部,
此致
答案 3 :(得分:0)
约瑟夫的答案对我来说遗漏了一个细节。我的表单和ajax调用是在index.ctp中调用/controller/edit.ctp所以我的$ this-&gt; Form-&gt;创建调用需要'action'=&gt;'/ controller / edit'添加到它。< / p>