且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

CakePHP ajax发布不断返回400错误请求

更新时间:2022-06-27 07:05:58

防止形式篡改的保护是安全组件提供的基本功能之一.只要启用,它将把所有POST都视为表单提交.

Protection against form tampering is one of the basic features provided by the Security Component. As long as it is enabled, it is going to treat all POSTs as form submissions.

启用了安全组件后,常规的手工编码HTML表单将无法使用,因此JQuery生成的POST也将无法使用.当然,您可以使用$this->Security->validatePost = false;$this->Security->csrfCheck = false;,但是随后您将松散安全组件提供的保护.

A regular hand-coded HTML form won't work with the Security Component enabled, so neither will a JQuery-generated POST. You can, of course, use $this->Security->validatePost = false; or $this->Security->csrfCheck = false; but then you loose the protection that the Security Component provides.

要保持安全组件的正常运行,您需要使用CakePHP Form Helper创建要通过ajax发布的表单.这样,data[_Token][fields]data[_Token][unlocked]隐藏字段将通过其键生成:

To keep the Security Component on and working as normal, you need to use the CakePHP Form Helper to create the form you're going to post via ajax. This way the data[_Token][fields] and data[_Token][unlocked] hidden fields get generated with their keys:

<?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发送该表单:

Now it's just a matter of serializing this form in JQuery so that it can be sent with the 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将成功.

Now if you press the submit button, the POST will succeed.

重要提示::由于Form Helper的令牌只能与安全组件一起使用,因此,仅当您打算每页生成一次POST时,此解决方案才有效.如果需要在两次页面重新加载之间多次发布相同的表单,那么在Controller的开头添加安全组件时,需要执行以下操作:

IMPORTANT: Due to the fact that the Form Helper's Tokens can only be used with the Security Component once, this solution only works if you only intend to POST once per page generation. If you need to be able to post the same form several times between page reloads then you'll need to do the following when you add the Security Component at the beginning of your Controller:

public $components = array(
    'Security' => array(
        'csrfUseOnce' => false
    )
);

...这将允许令牌用于多个请求.它不是安全的,但是您可以将其与csrfExpires结合使用,以使令牌最终失效.这全部记录在 CSRF配置部分中蛋糕书.

...this will allow the tokens to be used for more than one request. It's not as secure but you can combine it with csrfExpires so that the tokens will expire eventually. This is all documented in the CSRF configuration section of the Cake book.