2012-05-16 103 views
5

我打算在操作中使用ajax post。 GET請求正常工作,但是當我嘗試POST時,我在Firebug中看到'400 Bad Request',並且視圖返回'黑洞'響應。CakePHP ajax post不斷返回400錯誤的請求

這裏是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'); 
      } 
     }); 

這是由於蛋糕還是什麼的安全設置,我錯過這裏?

+0

我正在調查這個,我很確定它的安全組件阻止我在這裏: http://book.cakephp.org/2.0/en/core-libraries/components/security-component.html – kSeudo

+0

好吧如果我禁用這個跨站點安全:$ this-> Security-> csrfCheck = false; 它的工作.....但顯然這是不是要走的路:) 任何想法? – kSeudo

+0

你可以在/ usermgmt/users/editUser中發佈代碼 – Leo

回答

18

防護形式的篡改是由安全組件提供的基本功能之一。只要啓用,它將把所有POST視爲表單提交。

定期手動編碼的HTML表單在啓用安全組件時不起作用,因此JQuery生成的POST也不會生效。當然,您可以使用$this->Security->validatePost = false;$this->Security->csrfCheck = false;,但是這時您將失去安全組件提供的保護。

爲了保持安全組件正常運行,您需要使用CakePHP Form Helper來創建您要通過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每頁代一次纔有效。如果您需要能夠多次發佈相同的形式重新加載頁面之間,那麼你就需要做到以下幾點,當你在你的控制器的開頭添加安全組件:

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

...這將允許令牌用於多個請求。這不是作爲安全,但您可以將其與csrfExpires結合使用,以便令牌最終過期。這全部記錄在CSRF configuration section of the Cake book中。

+1

非常有幫助的答案 - 謝謝! – Dave

+2

只是想補充一點,因爲如果javascript修改了一個'hidden'輸入字段,也會發現錯誤,因爲令牌會跟蹤這些字段。如果您不想禁用validatePost,只需將字段從隱藏字段更改爲文本類型字段,然後通過css(display:none)隱藏它們。這將允許您的表單被正確提交,即使JavaScript更改了您的輸入字段。 – TeckniX

+0

非常好的和詳細的答案,這幫助我出了完全相同的問題,它會花我一段時間來找出它是SecurityComponent。 +1,先生! – Oldskool

0

製作舒爾你把功能editUser在:

public function beforeFilter(){ 
    parent::beforeFilter() 
    $this->Auth->allow('editUser'); 
    } 

UsersController內,

問候

0

約瑟夫的答案失蹤了我一個細節。我的表單和ajax調用在index.ctp中,並且正在調用/controller/edit.ctp,因此我的$ this-> Form-> create調用需要'action'=>'/ controller/edit'添加到它。

相關問題