Comment mettre en cache des formulaires avec un proxy inverse et gérer les jetons de formulaire périmés?

8

Lorsque l' API Form génère un formulaire, elle génère également un jeton qui est distribué avec le formulaire dans un champ masqué et qui doit être renvoyé. Si tel est le cas, le formulaire est traité.

Si une forme rendue est mise en cache, disons par Varnish , ce mécanisme se casse. Le premier utilisateur soumettant le formulaire consommera le jeton et les tentatives suivantes d'utilisation du formulaire seront rejetées.

Quelles stratégies sont disponibles pour que les formulaires continuent de fonctionner tout en mettant en cache leur formulaire rendu?

Létharion
la source
Es-tu sûr de ça? J'ai créé des sites avec des formulaires et des procurations inverses et je n'ai vu aucun problème. La seule chose que vous devez surveiller, en général, est de vous assurer que les pages de résultats ne sont pas mises en cache.
Alfred Armstrong
Je serais ravi d'avoir tort, car cela résoudrait mon problème, mais oui, j'en suis sûr. :) Vérifiez les fonctions form_ {g, s} et_cache pour plus de détails.
Letharion
Pour les utilisateurs anonymes, je suis sûr qu'une page avec un formulaire peut être mise en cache en toute sécurité. Pour les utilisateurs non anonymes, les procurations inverses sont problématiques dans tous les cas.
Alfred Armstrong
2
(Les jetons ne sont générés que lorsqu'un utilisateur possède un ID.)
Alfred Armstrong
1
Ah, ça a du sens. Malheureusement, mes utilisateurs dans ce cas sont authentifiés. Peut-être faudrait-il reformuler la question pour l'inclure.
Letharion

Réponses:

5

J'utilise BOA pour mes sites, mais par défaut, BOA désactive simplement la mise en cache frontale à la volée pour les soumissions de formulaires. Au-delà de mon expérience réelle, je suis tombé sur un artificiel d'un an sur la façon dont le New Zealand Post traite Drupal & Varnish et le problème des jetons de forme. Holy John Wayne, c'est une lecture incontournable pour la mise en cache Drupal - vraiment. En se concentrant uniquement sur le problème du formulaire:

La dernière pièce de notre puzzle est le module avancé de contournement du cache des cookies , qui définit automatiquement un cookie NO_CACHE spécial chaque fois que l'utilisateur soumet un formulaire POST sur le site, y compris des éléments comme le formulaire de connexion. Notre vernis est configuré pour contourner le cache de page (mais pas le cache ESI) lorsqu'il voit ce cookie.

Vous pouvez également désactiver les jetons de formulaire lorsque la production XSRF n'est pas requise avec dans form_alter (unset ($ form ['# token']));) ou ($ form ['# token'] = FALSE;)

Un article sur les performances d' Acquia Drupal propose un module Drupal Authcache , mais en lisant le document sur Authcache, il établit la mise en cache avec un espace réservé pour le formulaire (pas la mise en cache du formulaire):

Authcache tente d'intercepter tout contenu personnalisé et de configurer un espace réservé dans le code HTML. Ensuite, une fois la page chargée, un rappel Ajax est utilisé pour récupérer des données personnalisées et remplir les espaces réservés, mettant à jour dynamiquement le HTML de la page.

Espaces réservés Authcache actuels: jetons de formulaire (utilisateurs connectés uniquement; requis par> Drupal pour empêcher les attaques de contrefaçon de demande intersite)

La stratégie consiste à tout mettre en cache , sauf le formulaire . Donc, pour tout le reste: peut-être que Varnish n'est pas utilisé du tout, Memcache & Redis? Ma stratégie serait d'utiliser ce que BOA propose car j'utilise BOA et les assistants derrière lui ( omega8.cc ) en savent plus que moi. Je ne pense pas qu'il existe un cache externe qui résout le problème. Ils semblent tous contourner la forme.

Faites une mise en cache partielle avec l'authcache susmentionné et avec des vues et des panneaux finement modifiés, comme mentionné dans l'article du NZ Post et décrit par le brain trust de Wunderkraut - son ancien, mais résout le problème.

Utiliser le module Drupal ESI et le vernis est partiellement conforme ESI):

ESI - ou Edge Side includes - est une solution de mise en cache haute performance pour les utilisateurs authentifiés, mais peut également être utile pour les utilisateurs anonymes.

En règle générale, les pages personnalisées pour les utilisateurs authentifiés (même les personnalisations mineures, comme un bloc qui dit "Connecté en tant que manarth") empêcheront les procurations inverses (qui peuvent facilement fonctionner 100 fois plus rapidement que Drupal) de mettre la page en cache, car les messages destiné à un utilisateur pourrait alors être vu par un autre.

J'espère que c'est plus utile.

À M
la source
Un rapide coup d'œil au code suggère que le module ESI ne fait rien du tout en ce qui concerne la validation des formulaires; aucune mention de manipulation de jetons, ni aucune modification de forme intéressante. Est-il possible que vous n'ayez simplement pas mis en cache de formulaires nécessitant une authentification en vernis, et c'est pourquoi vous n'avez jamais vu ce problème?
Letharion
Il s'avère que c'est exactement ce qui se passe, BOA contourne le cache frontal à la volée pour les formulaires (désolé pour ma réponse précédemment incomplète / erronée). ESI est toujours une partie importante de la stratégie "cache tout sauf" maintenant dans ma réponse même si elle ne résout pas directement.
Tom
Cet article sur la Nouvelle-Zélande était vraiment très intéressant. Cependant, comme je peux le dire, il ne résout que le problème des jetons avec: "Dans les cas où vous êtes sûr que la protection XSRF n'est pas importante ... Drupal fournit un mécanisme pour désactiver les jetons de formulaire", ce qui n'est pas utile dans mon cas.
Letharion
Beaucoup d'informations utiles cependant, et certainement d'autres pourront l'appliquer à leurs problèmes. +1, et comme il ne reste qu'une heure, je pourrais aussi bien connaître la prime. :)
Letharion
0

Une solution potentielle serait de désactiver le jeton tous ensemble $form[‘#token’] = FALSE;, puis de remplacer le rappel de soumission à au lieu de publier le commentaire, de régénérer le formulaire d'origine avec un jeton et de demander à l'utilisateur de confirmer la publication.

Si l'utilisateur prend en charge ECMAScript , on pourrait améliorer l'expérience utilisateur en ayant une ressource de services qui expose la génération de formulaires de nouveaux jetons de formulaire et insère le formulaire pertinent dans le form_cache. Ensuite, dès que l'utilisateur se concentre sur le formulaire et est donc susceptible de vouloir le soumettre, désactivez le bouton de soumission, récupérez un nouveau jeton et insérez-le dans le formulaire déjà rendu, puis réactivez le bouton de soumission.

Létharion
la source