2012-05-16 15 views
5

Tring używać postu ajaxowego do działania. Żądania GET działają dobrze, ale kiedy próbuję POST, widzę "400 Bad Request" w firebug, a widok zwraca odpowiedź "Black hole".Posta CakePHP ajax powraca 400 złych żądań

Oto prośba 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'); 
      } 
     }); 

Jest to spowodowane ustawieniami bezpieczeństwa ciasto lub co ja tu brakuje?

+0

Zajmuję się tym i jestem prawie pewien, że komponent Security mnie tu zatrzymał: http://book.cakephp.org/2.0/en/core-libraries/components/security-component.html – kSeudo

+0

OK, więc jeśli wyłączę zabezpieczenia między lokacjami: $ this-> Security-> csrfCheck = false; Działa ..... ale oczywiście to nie jest droga do celu :) Czy masz pomysł? – kSeudo

+0

Czy możesz opublikować kod w/usermgmt/users/editUser – Leo

Odpowiedz

18

Ochrona przed formą sabotażu jest jedną z podstawowych funkcji oferowanych przez komponent zabezpieczający. Dopóki jest włączona, wszystkie zgłoszenia POST będą traktowane jako zgłoszenia do formularza.

Zwykły ręcznie kodowany formularz HTML nie działa z włączonym komponentem zabezpieczeń, dlatego też nie będzie generowany POST przez JQuery. Możesz oczywiście użyć $this->Security->validatePost = false; lub $this->Security->csrfCheck = false;, ale stracisz ochronę zapewnianą przez Ochronę.

Aby komponent Security był włączony i działa normalnie, musisz użyć CakePHP Form Helper, aby utworzyć formularz, który zamierzasz opublikować przez ajax. W ten sposób ukryte pola data[_Token][fields] i data[_Token][unlocked] generowana z ich klucze:

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

ten wygeneruje coś takiego:

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

Teraz to tylko kwestia szeregowania tego formularza w JQuery tak, że może wysłane z ajaxem 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 
    }); 

Teraz, jeśli naciśniesz przycisk przesyłania, POST się powiedzie.

WAŻNE: Ze względu na fakt, że Żetony postaci pomocnika może być używany tylko z elementem bezpieczeństwa raz, to rozwiązanie działa tylko jeśli tylko zamierza POST raz na pokolenie strony. Jeśli potrzebujesz, aby móc pisać tej samej formie wielokrotnie między przeładowywanie następnie trzeba wykonać następujące czynności po dodaniu elementu zabezpieczenia na początku swojej Kontroler:

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

... to wolę umożliwić używanie tokenów dla więcej niż jednego żądania. Nie jest on bezpieczny, ale można go łączyć z csrfExpires, aby ostatecznie wygasły tokeny. Wszystko to jest udokumentowane w CSRF configuration section of the Cake book.

+1

Bardzo pomocna odpowiedź - dziękuję! – Dave

+2

Po prostu chciałem dodać do tego trochę, ponieważ błąd zostanie znaleziony również wtedy, gdy javascript modyfikuje "ukryte" pole wejściowe, tak jak token je śledzi. Jeśli nie chcesz wyłączać validatePost, po prostu zmień pola z ukrytych na pola tekstowe, a następnie ukryj je za pomocą css (display: none). Umożliwi to prawidłowe przesłanie formularza, nawet jeśli javascript zmieni twoje pola wprowadzania. – TeckniX

+0

Bardzo dobra i szczegółowa odpowiedź, pomogła mi rozwiązać dokładnie ten sam problem i zajęłoby mi to trochę czasu, zanim zorientowałem się, że to SecurityComponent. +1 dla ciebie, sir! – Oldskool

0

Producent Shure jesteś oddanie editUser funkcja w:

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

wewnątrz UsersController,

Pozdrowienia

0

odpowiedź Józefa zaginął jeden szczegół dla mnie.Moja forma i wywołanie ajaxa znajdowały się w index.ctp i wywoływały /controller/edit.ctp, więc moje $ this-> Form-> create call needed "action" => '/ controller/edit "zostało dodane do niego.

Powiązane problemy