2012-05-16 19 views
5

Sto tentando di utilizzare un post ajax per un'azione. Le richieste GET funzionano bene, ma quando provo a POST vedo una '400 Bad Request' in firebug e la vista restituisce una risposta 'Black hole'.CakePHP post ajax continua a restituire 400 Bad Request

Ecco la richiesta 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'); 
      } 
     }); 

È questo a causa delle impostazioni di sicurezza di torta o quello che mi manca qui?

+0

Sto osservando questo e sono abbastanza sicuro che il componente di sicurezza mi fermi qui: http://book.cakephp.org/2.0/en/core-libraries/components/security-component.html – kSeudo

+0

Ok così se disattivo la sicurezza cross-site con questo: $ this-> Security-> csrfCheck = false; Funziona ..... ma ovviamente questa non è la strada da percorrere :) Qualche idea? – kSeudo

+0

puoi pubblicare il codice in/usermgmt/users/editUser – Leo

risposta

18

Protezione contro la forma manomissione è una delle caratteristiche di base fornite dal componente di protezione. Finché è abilitato, tratterà tutti i POST come invii di moduli.

Un normale modulo HTML codificato manualmente non funziona con il componente di sicurezza abilitato, quindi nemmeno un POST generato da JQuery. Naturalmente, è possibile utilizzare $this->Security->validatePost = false; o $this->Security->csrfCheck = false; ma si perde la protezione fornita dal Componente di sicurezza.

Per mantenere il Componente di sicurezza attivo e funzionante come al solito, è necessario utilizzare l'Assistente per moduli CakePHP per creare il modulo che si invierà tramite Ajax. In questo modo i campi nascosti data[_Token][fields] e data[_Token][unlocked] vengono generati con le loro chiavi:

<?php 
    echo $this->Form->create('Test',array('id'=>'testform')); 
    echo $this->Form->input('Something'); 
    echo $this->Form->submit(); 
    echo $this->Form->end(); 
?> 

Questo genererà qualcosa di simile:

<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> 

Ora è solo una questione di serializzare questo modulo in JQuery in modo che possa essere inviato con l'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 
    }); 

Ora, se si preme il pulsante di invio, il POST avrà esito positivo.

IMPORTANTE: A causa del fatto che il token è la forma di supporto può essere utilizzato solo con il componente di protezione una volta, questa soluzione funziona solo se si intende intervenire solo una volta per generazione pagina. Se avete bisogno di essere in grado di pubblicare lo stesso modulo più volte tra pagina viene ricaricata, allora è necessario eseguire le seguenti operazioni quando si aggiunge il componente di protezione all'inizio del Controller:

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

... questa volontà consentire che i token siano utilizzati per più di una richiesta. Non è come sicuro, ma è possibile combinarlo con csrfExpires in modo che i token scadrà alla fine. Tutto questo è documentato nello CSRF configuration section of the Cake book.

+1

Risposta molto utile - grazie! – Dave

+2

Volevo solo aggiungere un po ', poiché l'errore verrà trovato anche se javascript modifica un campo di input "nascosto", poiché il token tiene traccia di quelli. Se non si desidera disabilitare il validatePost, è sufficiente modificare i campi da nascosti a campi di testo, quindi nasconderlo tramite css (display: none). Ciò consentirà al modulo di essere inviato correttamente, anche se javascript modifica i campi di input. – TeckniX

+0

Risposta molto buona e dettagliata, questo mi ha aiutato a risolvere esattamente lo stesso problema e mi ci sarebbe voluto un po 'per capire che si trattava di SecurityComponent. +1 per te, signore! – Oldskool

0

Fai shure si sta mettendo la funzione editUser in:

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

all'interno di UsersController,

saluti

0

risposta di Joseph mancava un dettaglio per me.Il mio modulo e la chiamata ajax erano in index.ctp e chiamavo /controller/edit.ctp quindi il mio $ this-> Form-> creava la chiamata necessaria 'action' => '/ controller/edit' aggiunta ad essa.

Problemi correlati