2009-03-16 5 views
4

J'ai découvert que le composant de sécurité dans CakePHP aide à prévenir CSRF en ajoutant des jetons comme valeurs cachées aux formulaires. Ce que je me demandais, c'est s'il y avait moyen d'empêcher les soumissions de formulaires en double en utilisant ce composant ou un autre composant/assistant?Comment éviter les soumissions de formulaires doubles/dupliqués dans CakePHP?

Dans les projets précédents, j'ai utilisé un hachage unique enregistré dans une session, qui est lu puis supprimé lors de la soumission. Une soumission répétée aurait le même hachage et une erreur serait produite.

grâce

Répondre

0

Je ne sais pas gâteau, mais essayez d'afficher le contenu d'une non requête POST, faire une auto redirect. Le double post sera résolu.

+0

Pas particulièrement utile - gâteau est généralement d'avoir la configuration des formulaires de retour après eux-mêmes. Il vaut mieux continuer aussi, car vous obtenez beaucoup de choses (comme remplir automatiquement les champs d'une erreur de validation) avec ça. –

2

Vous pourriez implémenter le même type de chose dans Cake que vous avez déjà fait.

Lors de la soumission, définissez une variable de session indiquant que ce formulaire a été envoyé. Assurez-vous de mettre une heure d'expiration après (dans quelques secondes devrait faire l'affaire). Si la variable de session est présente lorsque vous traitez le formulaire (et que vous êtes dans cette période d'expiration), vous devez soumettre une nouvelle requête, donc n'enregistrez pas les données du formulaire.

Je vous recommande de le faire dans la méthode save (..) de votre modèle, vous n'avez donc pas besoin de vous soucier de l'ajouter dans plusieurs emplacements de code.

+0

Je vois d'où vous venez, mais je ne pense pas que vous devriez accéder à SessionComponent à partir de la couche modèle. :) – deizel

+0

Je suis d'accord, ce n'est pas joli. Parfois, cependant, je suis prêt à briser le modèle MVC dans l'intérêt de faire quelque chose. –

+0

S'il vous plaît montrer un exemple !! –

0

Le composant de sécurité devrait fonctionner, en outre, vous pouvez également unset les données juste après le poste:

unset($this->data['yourModel']); 
2

Il existe une fonction dans CakePHP 2.x dans le composant de sécurité qui vous permet de choisir de utilisez le même jeton de sécurité jusqu'à ce qu'il expire ou juste une fois. Placez dans vos contrôleurs méthode beforeFilter:

$this->Security->csrfUseOnce = true; 

Trouver plus d'informations here

1

Il suffit de faire très simple PRG Pattern droit de ..Il ?! Eh bien, au moins c'est ce que tout le monde dit mais personne ne publie de réponse claire! Il m'a fallu une semaine de recherche et de creusage, puis le "Newbie" a décidé de faire quelque chose par lui-même! Voici une façon de le faire dans CakePHP (j'utilise 2.0.5):

Quelle que soit le code est ici la logique dans les étapes: 1-
données définies
2- validate (ne pas créer() encore)
3- écrire $ this-> request-> données à une variable de session
4- redirigent à une action SAVEDATA

intérieur une action SAVEDATA:
5- lire & enregistrer la variable session de SUPPRIMER
6 de la session de variable
7- create()
8 enregistrer des données pour modéliser
9- redirigent

Voici un exemple de la façon dont votre code pourrait ressembler.
** Attn: "ourController" et "ourModel"

public function add() { 
     if ($this->request->is('post')) { 
      if (isset($this->request->data)) { 
       $this->ourModel->set($this->request->data); 
       if ($this->ourModel->validates()) { 
        $this->Session->write('myData', $this->request->data); 
        $this->redirect(array('controller' => 'ourController', 
              'action' => 'saveData', 
              'ourModel' //optional but recommended 
             ) 
            ); 
       } else { 
        $this->Session->setFlash('ourModel could not be saved.'); 
        } 
      } 
.....//the rest of add() function 
} 

alors vous devriez être redirigé (sur la validation) à cette fonction qui vous redirige à nouveau à l'action d'index ou chaque fois que votre logique vous prend!

public function saveData($model) { 
     $myData = $this->Session->read('myData'); 
     $this->Session->delete('myData'); //extremely important 
     $this->$model->create(); 
     if ($this->$model->save($myData)) 
       // or $myData[$model] if you are dealing with multiple models 
       { 
       $this->Session->setFlash(__($model.' have been saved successfully')); 
       $this->redirect(array('controller' => 'ourController', 
            'action' => 'index' 
            ) 
           ); 
      } 
     } else{ 
      $this->Session->setFlash(__($model.' could not be saved')); 
     } 
     } 
    } 

Une auto-simple redirection pourrait fonctionner mais dans la plupart des cas, vous souhaitez rediriger vers un point de vue différent (par exemple, à une autre forme ou à la vue index)

J'espère que cette élaboration permet de gagner du temps sur les autres si ne pas avoir à perdre une semaine entière (comme dans mon cas) juste pour faire une telle fonctionnalité côté serveur!

2

@DoctorFox a déjà répondu avec csrfUseOnce = true, mais cela vous jettera dans les trous noirs que vous avez encore à gérer. Donc, la solution complète pour moi est:

class YourAppController extends AppController { 

    public $helpers = array('Html', 'Form'); 
    public $components = array('Security'); 

    public function beforeFilter() { 
     $this->Security->csrfUseOnce = true; 
     $this->Security->blackHoleCallback = 'blackhole'; 
    } 

    public function blackhole($type) { 
     $this->redirect(array('action' => 'index')); 
    } 

S'il n'y a pas de redirection, vous êtes toujours ouvert pour la soumission en double formulaire.

Ref: CakePHP security component

1

Je suis puted événement onClick qui désactive le bouton comme ceci:

<?= $this->Form->button('Salvar', [ 
        'value' =>'Submit', 
        'onClick' => 'form.submit();this.disabled=true' 
]) 
?> 
Questions connexes