IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

empêcher l'insertion multiple en cas de réinitialisation


Sujet :

Langage PHP

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 221
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 221
    Points : 472
    Points
    472
    Par défaut empêcher l'insertion multiple en cas de réinitialisation
    Bonjour à tous,

    j'ai un petit problème, somme toute classique mais nouveau pour moi :

    Lorsqu'un visiteur poste un commentaire, celui-ci s'affiche tout de suite dans la page.

    Si par hasard il réactualise la page, il y a donc une boite de dialogue "les informations seront renvoyées" qui s'ouvre.
    Donc le message se retrouve une deuxième fois dans la base de donnée et s'affiche deux fois, ce qui est pour le moins ridicule et pathétique.

    Donc : Comment faire pour empêcher ce renvoi des données d'un formulaire déjà validé en cas de réinitialisation d'une page ?


    Merci d'avance pour vos réponses.

  2. #2
    Membre expérimenté
    Avatar de Anduriel
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Février 2004
    Messages
    2 290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration

    Informations forums :
    Inscription : Février 2004
    Messages : 2 290
    Points : 1 500
    Points
    1 500
    Par défaut
    Ce que je fais, quand le formulaire posté et les informations traitées, je redirige l'utilisateur vers la même page avec un META EQUIV ou un header si aucune en-tete n'est envoyée avant.
    Comme ça, il peut réactualiser mais ça ne changera rien.

  3. #3
    Membre confirmé Avatar de dj-julio
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    745
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Décembre 2005
    Messages : 745
    Points : 625
    Points
    625
    Par défaut
    ou alors une autre solution
    en même temps que tu stock son message (et je suppose la date) dans la base de données,
    stock également sont adresse ip

    comme ça avant d'envoyer le message, tu fais une verification avec l'ip et la date du dernier message posté par la personne ;-)

  4. #4
    Expert éminent Avatar de Mr N.
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    5 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 5 418
    Points : 6 449
    Points
    6 449
    Par défaut
    Deux méthodes que tu peux combiner :
    - jeton : le formulaire possède un jeton à usage unique. une fois ce jeton consommé, impossible de retraité le formulaire.
    - redirection : a chaque mise à jour de la base, tu fais une redirection. Ainsi, l'utilisateur ne peut pas faire refresh. (comme quand tu poste un message sur ce forum d'ailleurs)

  5. #5
    Expert éminent Avatar de Mr N.
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    5 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 5 418
    Points : 6 449
    Points
    6 449
    Par défaut
    Citation Envoyé par dj-julio
    ou alors une autre solution
    en même temps que tu stock son message (et je suppose la date) dans la base de données,
    stock également sont adresse ip

    comme ça avant d'envoyer le message, tu fais une verification avec l'ip et la date du dernier message posté par la personne ;-)
    Et s'il partage son ip avec d'autres personnes, comme dans une entreprise par exemple ?

  6. #6
    Membre confirmé Avatar de dj-julio
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    745
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Décembre 2005
    Messages : 745
    Points : 625
    Points
    625
    Par défaut
    et bah là on est pas dans la M****

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 221
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 221
    Points : 472
    Points
    472
    Par défaut
    La vache 5 réponses en si peu de temps, merci !

    Je viens de résoudre le problème :

    Après l'insertion dans la base, j'efface une variable V. Puis pour le script qui insère je fais un test : si la variable V n'est pas vide tu insères, sinon tu exploses.

    ça va sauter dans les foyers !

    Sinon l'idée des jetons est peut-être à creuser, c'est quoi le principe, ça sert à quoi en général? il faut des sessions non ?

  8. #8
    Membre régulier Avatar de KneXtasY
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 121
    Points : 109
    Points
    109
    Par défaut
    Citation Envoyé par Anduriel
    Ce que je fais, quand le formulaire posté et les informations traitées, je redirige l'utilisateur vers la même page avec un META EQUIV ou un header si aucune en-tete n'est envoyée avant.
    Comme ça, il peut réactualiser mais ça ne changera rien.
    Et si l'utilisateur recule d'une page (<-) ?
    On a le même problème ...

    L'idée du jeton me semble bien.
    Il faut regarder que la page d'origine corresponde bien avec celle du formulaire.
    Si c'est le cas, on insère les données dans la base et on marque le formulaire en session comme traité.

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 221
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 221
    Points : 472
    Points
    472
    Par défaut
    Et mon idée elle n'est pas bien alors ?

  10. #10
    Membre régulier Avatar de KneXtasY
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 121
    Points : 109
    Points
    109
    Par défaut
    Le principe est bon.

    Mais quand tu parles de variable V, c'est assez flou.
    Elle vient d'ou ? Elle est initialisée quand ?

    Car si tu l'initialises au début du script d'insertion, lorsque la page est relancée, le script s'execute a nouveau et la variable se reinitialise.

    D'ou l'idée de la mettre en session.

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 221
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 221
    Points : 472
    Points
    472
    Par défaut
    En fait le visiteur poste le formulaire.

    Dans ce formulaire il y a une variable $contenu issue du textarea.

    En validant, le script d'insertion insère toutes les variables du formulaire, à condition que la variable $contenu soit rempli.

    Après l'insertion, la variable $contenu est vidée.

    (tout se passe sur la même page, pas de refresh ou de page spécifique pour la validation)


    Donc ensuite, si le visiteur raffraichit la page web après avoir posté un message, comme la variable $contenu vient d'être vidée, le script d'insertion ne fonctionne plus.


    ça tiens en 2 lignes de codes et ma foi je ne vois pas de problème avec ce système, mais si quelqu'un en voit un, qu'il n'hésite pas :-)

  12. #12
    Membre régulier Avatar de KneXtasY
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 121
    Points : 109
    Points
    109
    Par défaut
    Oki !

    Mais dans ce cas, si j'ai bien compris, le traitement se fait dans le même fichier que la définition du formulaire.

    En fait j'ai toujours utilisé un target autre que la page du formulaire c'est pour ça !

  13. #13
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 221
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 221
    Points : 472
    Points
    472
    Par défaut
    Euh... En fait je me suis quelque peu fourvoyé, mon idée ne fonctionne pas du tout.

    J'ai cru que cela fonctionnait puisque le nouveau message ne s'affichait pas, mais en fait c'est le système anti-flood qui faisait ça. Passé 20 seconde, le message se réaffichait et après réflexion c'est logique, puisque j'ai beau vider la variable $contenu, celle-ci est réinitialisée par le rafraichissement de la page

    Mais, comme j'ai un gros cerveau et des petits doigts musclés, j'ai retrouvé une solution qui cette fois fonctionne 8) :

    En postant le formulaire, je teste la valeur md5() du champ contenu et je l'insère dans la base.
    Au moment de l'insertion dans la base, je fais une requête pour récupérer les tuples qui comportent le même md5() pour la même IP.
    Si il n'y a pas de résultat, alors j'insère, sinon rien du tout.

    Cette fois cela fonctionne bien.
    Me direz-vous envoyer les données du formulaire vers une nouvelle page eut été plus simple, je vous répondrais alors que c'est un fait, mais j'aime bien que lorsque l'on poste un commentaire on se retrouve immédiatement sur la même page avec le commentaire affiché comme par magie.

    Question: Voyez-vous un inconvénient à ma méthode, avant que je n'en dépose le brevet ?

  14. #14
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 221
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 221
    Points : 472
    Points
    472
    Par défaut
    Une question plus précise :

    Pensez-vous qu'il vaut mieux utiliser md5() ou sha_file() ou crc32() ?

    en terme de temps d'exécution par exemple ?

    ça ne change rien me direz-vous de toute façon le parseur compare dans tous les cas des chaines de 32 caractères dans le champ de la base.

  15. #15
    Expert éminent Avatar de Mr N.
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    5 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 5 418
    Points : 6 449
    Points
    6 449
    Par défaut
    Inconvénient ? oui : performances ! md5 n'est pas trivial, en plus le faire sur toutes les lignes à chaque insertion... ou alors tu le stock une fois pour toute dans une colonnes dédiée mais là encore cette colonne n'est pas vraiment "NF-friendly" car il y a comme une redondance entre le message et la dite colonne.
    De plus tu ne répond pas exactement au problème de re-soumission intempestive de commentaire, mais à la présence de doublon dans ta base (ce qui peut revenir au même mais pas exactement). Ainsi, si tu te débrouilles bien (ou mal suivant le point de vue), tu ne permettras pas à quelqu'un de poster un commentaire qui serait l'identique d'un autre commentaire sur un autre article/produit/service...

  16. #16
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 221
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 221
    Points : 472
    Points
    472
    Par défaut
    Oui ce que tu dis est vrai, mais ne correspond pas à ce que j'ai fait.

    Je me suis mal expliqué, je recommence en expliquant.

    -Le visiteur poste un formulaire.
    -Je transforme la valeur du champ textarea en chaine de caractère avec md5().
    - j'insère le textarea dans la base (bien sur), mais aussi dans un champ distinct la valeur de son md5(), ainsi que son IP (pour l'antiflood, c'est autre chose).

    Avant l'insertion dans la base, je sélectionne les tuples dont l'ip, la valeur md5() et le numéro de la page correspondent avec le nouveau formulaire posté.

    Si le gars a reposté exactement la même chose pour la même page ça ne fonctionne pas (c'est tout de même peu probable et de toute façon pas intéressant), mais surtout si le gars en question à réinitialisé la page alors la non plus ça ne fonctionne pas et c'est bien le résultat souhaité.

    Si quelqu'un d'autre poste exactement la même chose, n'ayant pas la même IP, ça ne gêne pas et si notre bonhomme poste exactement la même chose mais sur une autre page, ça fonctionne.

    Bien sur si un gars revient avec la même IP, poster la même chose, sur la même page alors ça ne fonctionnera pas mais bon là c'est triste quand même.


    Donc je viens de tester ça fonctionne bien, la seule question que je me pose en effet est la performance car si le gars poste un formulaire et qu'il y a 5000 commentaires il va falloir comparer le md5() de son formulaire avec 5000 autres chaines de caractères.

    Mais bon est-ce vraiment un problème, puisque l'on ne le fait que pour un formulaire ?
    Même si il y avait 5000000 commentaires, est-ce que cela serait encore un problème ?

    Le gars peut bien patienter 3 secondes avant que son commentaire soit inséré, non? Après tout si il arrivait sur une nouvelle page, il lui faudrait cliquer sur un lien pour revenir à la page précédente.

    Je me trompe ?


    Ceci dit je suis tout à fait d'accord pour dire que ce n'est pas la perfection mathématique pure, puisqu'il reste un risque d'erreur même minime.
    Mais question performance donc ?

  17. #17
    Expert éminent Avatar de Mr N.
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    5 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 5 418
    Points : 6 449
    Points
    6 449
    Par défaut
    Dis comme ça c'est mieux que ce que j'avais compris... Donc tu empêches les doublons, ce qui empeche par la même occasion la re-soumission de formulaire intempestive.
    Pour les perf, ben je dirais à toi de voir. Tu te fais une base de test, tu fais une petite boucle qui génère un md5 sur l'incrément par exemple tu le mets en base, et ensuite tu fais des requêtes dessus sous PhpMyAdmin pour voir comme ton système répond.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    $values = ' ('. md5('0') .')';
    for ($i = 1 ; $i < 5000 ; $i++) {
       $values .= ', ('. md5($i) .')';
    }
    $sql = "INSERT INTO ma_table_de_test(md5) VALUES ". $values;
    ...

  18. #18
    Membre habitué
    Inscrit en
    Août 2005
    Messages
    142
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 142
    Points : 156
    Points
    156
    Par défaut
    Question performance, c'est sur que ce n'est pas la meilleur solution surtout qu'avec une petite redirection apres le post tu n'aurai pas a faire cette fatiquante comparaison pour la bdd.

    Cela dit, ce topic m'interesse car je suis confronté à la même intrigue.

    Il m'est soudainement venu une petite idée grace à celle du jeton de Mr N. Dans ton formulaire dans un input caché, tu place un code unique. Ce code est enregistré dans la bdd avec le commentaire. Et lors de l'insertion, tu na qua verifier que ce code n'est pas deja present. Ainsi tu sais si l'utilisateur s'amuse avec la touche F5.

  19. #19
    Expert éminent Avatar de Mr N.
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    5 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 5 418
    Points : 6 449
    Points
    6 449
    Par défaut
    Je trouve dommage de mettre ce code dans la bd. Personnelement je ferais comme ceci :
    1. l'utilisateur demande une page ou un formulaire est présent.
    2. Génération d'un jeton. Ce jeton est placé en session et dans le formulaire.
    3. L'utilisateur soumet le formulaire.
    4. On compare le jeton avec celui en session
    4.1 le jeton est valide, on fait la mise à jour + suppression du jeton en session + redirection (bonus)
    4.2 le jeton n'est pas valide (inexistant en session ou différent), on dis poliment au gugusse d'arrêter de faire mumuse.

    Du coup pas de requete dans la bd pour vérifier... Et la bd contient seulement des données, pas des hacks de vérification.

  20. #20
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 221
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 221
    Points : 472
    Points
    472
    Par défaut
    Bon alors, réflexion faite, je suis revenu à ce que j'avais fait la première fois :

    Quand le visiteur valide le formulaire, cela expédie les informations sur une nouvelle page qui insère celles-ci dans la base de donnée.

    Cette nouvelle page est vide (juste un fond coloré pour éviter la page blanche) et il y a un meta-refresh d'une seconde pour revenir à la page précédente.

    C'est tout de même beaucoup plus léger pour la base, même si ça peut surprendre un peu le visiteur la première fois.


    Vous en pensez quoi ?

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [debutant][code] insert multiple de valeurs
    Par topaze dans le forum Oracle
    Réponses: 9
    Dernier message: 29/11/2005, 15h22
  2. procédure stockée insert multiple
    Par gigi34 dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 20/09/2005, 10h37
  3. Insertion multiple à base de sous requête SELECT
    Par drinkmilk dans le forum Langage SQL
    Réponses: 8
    Dernier message: 14/04/2005, 16h34
  4. INSERT multiples avec : rs.AddNew et .Update
    Par M.Zip dans le forum ASP
    Réponses: 4
    Dernier message: 03/12/2004, 15h53
  5. pb d'insertions multiples
    Par devalender dans le forum SQL
    Réponses: 2
    Dernier message: 14/07/2004, 14h49

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo