Question

Dites, vous soumettez un formulaire, ce qui affecte votre base de données (ajout d'enregistrements / les supprimer / les mettre à jour), ce qui est la façon dont votre demande ressemble à:

POST / application / action = update

Maintenant, par exemple, vous avez terminé votre mise à jour, de sorte que vous souhaitez l'utilisateur vers la page d'accueil.

response.sendRedirect / application / action = accueil

Cela fonctionne à merveille. L'utilisateur est envoyé une redirection après le POST, même si l'utilisateur tente de rafraîchir la page en appuyant sur F5, vous êtes bien. Cependant, cela ne fonctionnera pas si vous avez fait ceci:

RequestDispatcher.forward (/ application / action = home)

Étant donné qu'il ya un scénario dans lequel vous devez afficher différents types de messages d'erreur / succès une fois que vous avez terminé votre mise à jour, vous faites le plus probablement en avant après le POST. Dans un tel scénario, comment voulez-vous éviter les actions de mise à jour de se produire deux fois?

Je trouve plutôt amusant que de nombreux sites sécurisés (banques) / passerelles de paiement ont tendance à informer l'utilisateur en plaçant le texte à l'écran, tels que « S'il vous plaît ne pas appuyer en arrière / boutons de rafraîchissement ».

Yat-il meilleure façon de traiter ce? Autre que demander à l'utilisateur de ne pas appuyer sur ces boutons? Quand je la dernière vérification, il y avait quelque chose appelé la « verticale Response Cache ». Un filtre qui permettrait d'identifier le caractère unique de votre demande dans une session et tente d'envoyer une réponse en cache si la demande est en double. Y a-t-il des moyens plus simples pour résoudre ce problème classique?

Voici un lien vers la solution de cache de réponse verticale dont je parlais: http: / /www.fingo.info/en/articles/_1.html . Je suis toutefois pas certain de la façon dont cela fonctionne vraiment.

Était-ce utile?

La solution

Une pensée que j'ai eu est d'intégrer un identifiant unique (probablement une chaîne aléatoire) comme un champ de formulaire caché sous la forme qui est-POST soumis. La chaîne d'identification peut être mis dans la base de données comme un « ID de transaction ». Maintenant, quand vous allez mettre à jour la base de données, vérifiez d'abord s'il y a un enregistrement existant avec l'ID de transaction soumise, et si oui, supposons que c'est un double et ne changent pas la base de données.

Bien sûr, comme je l'ai dit, cela est juste une pensée. Je ne sais pas quelles sont les méthodes réellement utilisées dans la pratique. (Je soupçonne que beaucoup de sites moins critiques ignorent tout le problème et espèrent que leurs utilisateurs seront intelligents ... une proposition perdante si j'ai jamais vu un; -)

EDIT : comme indiqué dans les commentaires, le stockage des ID de transaction dans la base de données peut prendre beaucoup d'espace, mais si c'est un problème, vous pouvez garder un cache en mémoire de toutes les transactions ID traités au cours des 5 dernières minutes / 1 heure / 1 jour / que ce soit. Cela devrait fonctionner à moins que vous êtes contre un pirate déterminé ...

Autres conseils

Oui, je crois que vous devriez rediriger après un POST, à l'exception des demandes de l'API. Sans cela non seulement vous avez à vous soucier de faire double POSTs lorsque l'utilisateur utilise le bouton de retour, mais le navigateur sera également donner à l'utilisateur des dialogues ennuyeux quand ils essaient d'utiliser le bouton de retour.

response.sendRedirect fonctionne dans la pratique, mais en ce tecnically envoie le mauvais code de réponse HTTP à cet effet. sendRedirect envoie un 302, mais le bon code à utiliser pour transformer un POST en un GET est 303. (la plupart des navigateurs traiteront 302 comme un 303 si elles obtiennent en réponse à un POST, cependant)

En général, vous voulez la redirection d'envoyer l'utilisateur à tout point de vue affiche l'effet de leur changement. Par exemple, s'ils éditent un widget, ils devraient être redirigés vers la vue de ce widget. S'ils suppriment un widget, ils devraient être redirigés vers le point de vue que le widget aurait paru quand il existait (peut-être la liste des widgets).

Parfois, il est agréable d'avoir un message d'état à la maison conduire davantage le fait qu'une action a eu lieu. Une façon simple de faire est d'avoir un paramètre commun à votre point de vue que, lorsqu'il est réglé, affiche un message rempli d'action. par exemple:

/widget?id=12345&msg=Widget+modified.

Ici, le paramètre "msg" contient le message "Widget modifié". Le seul inconvénient de cette approche est qu'il peut être possible pour les sites malveillants pour donner à vos utilisateurs des messages confus / trompeurs. par exemple:

/account?msg=Foo+Corp.+hates+you.

Si vous êtes vraiment inquiet à ce sujet vous pouvez inclure une signature expirant le message comme un paramètre supplémentaire. Si la signature est invalide ou a expiré, il suffit de ne pas afficher le message.

La meilleure solution pour résoudre le problème de montrer les messages d'état aux utilisateurs après un POST GET redirection est d'utiliser les sessions utilisateur.

Comment

Ajouter des attributs à la session utilisateur avec une valeur comme un ensemble de messages à afficher. pour exemple.

userSession.put("success_messages", new HashSet<String>(){"Success", "Check your account balance"});
userSession.put("warning_messages", new HashSet<String>(){"Your account balance is low. Recharge immediately"});

Et un filtre qui balaye la session utilisateur pour ces attributs particuliers et délivre les messages. Le filtre doit supprimer les attributs après avoir lu une fois, comme les messages d'état sont généralement affichés qu'une seule fois.

Je trouve plutôt amusant que de nombreux sites sécurisés (banques) / passerelles de paiement ont tendance à informer l'utilisateur en plaçant le texte à l'écran, tels que « S'il vous plaît ne pas appuyer en arrière / boutons de rafraîchissement ».

certaines personnes trouvent son mieux « désactiver tous Retour, événement Actualiser sur ces pages critiques »; Je ne sais pas si cela est bon ou non.

Mais votre solution contenait la "cache de réponse vertical " sonne bien

Il est un peu non évidente mais:

  • créer un objet dans la calée session utilisateur.
  • la valeur est une demande + java avenir pour le résultat
  • revenir immédiatement avec une redirection côté client.
  • alors que la redirection côté client est en cours de traitement, un travail de thread de travail sur la production de la réponse.

Alors au moment où le navigateur client vient compléter la redirection, obtenir des images de la nouvelle page, etc ... les résultats sont en attente pour l'utilisateur.

L'alternative est de rendre l'utilisateur douloureusement conscient de combien de temps la base de données prend.

Mise à jour de sécurité (jan 2011 24):

La clé est vulnérable à l'attaque car il fait partie de la réponse au client, donc

  1. Générer une clé aléatoire
  2. Utilisez l'identifiant de session de l'utilisateur sous forme de sel pour créer un SHA-1
  3. magasin à la fois la clé aléatoire et le SHA-1 dans la base de données (,) comme la clé primaire. (Pas d'indexation séparée sur le RANDOMKEY.
  4. Utilisez les deux RANDOMKEY et le SHA-1 en tant que db recherche.
  5. Ne pas stocker la session Id (éviter les problèmes de confidentialité à pouvoir corollate de nombreuses entrées au même utilisateur)
  6. Expirez les résultats au bout de 2-3 jours. (Permet un traitement par lots tous les jours pour faire le nettoyage et évite des problèmes pour créer des sessions utilisateur qui sont durables semi-long)

Cette méthode exige que tout pirate de connaître à la fois l'identifiant de session et la clé aléatoire.

Cette approche peut sembler exagéré, mais un mécanisme de redirection durci peut être utilisé pour des situations comme les réinitialisations de mot de passe.

Si vous travaillez avec les scripts côté serveur java et aussi à l'aide des entretoises 2 vous faites référence ce lien qui parle sur l'utilisation de jetons.

http://www.xinotes.org/notes/note/369/

Un jeton doit être généré et maintenu en session pour la première page rendu, lorsque la demande est soumise avec le jeton pour la première fois, dans l'action des entretoises courir un fil avec le nom de fil comme l'ID jeton et exécuter la logique tout le client a demandé pour, lorsque le client soumet à nouveau la même demande, vérifier si le fil est toujours en cours (thread.getcurrentthread (). interrompu) si vous utilisez encore, puis envoyer un client redirect 503.

S'il vous plaît regardez la ExecuteAndWaitInterceptor des entretoises 2code, la logique de ce combiné avec jeton aider clic rapide

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top