Mysql, lock et PHP

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Mysql, lock et PHP

par webaida » 05 juin 2009, 09:39

Bonjour,

merci pour tout ça :)
Je pensais effectivement en ajax repousser le timestamp, je pense que c'est une bonne solution.
Par contre je n'avais pas pensé à l'identifiant unique repris dans les pages ... merci !

par loboblahz » 31 mai 2009, 15:48

Bonjour,

Je travailles depuis 1995 sur 4D, et j'ai aussi passé sur du PHP/MySQlL plusieurs de mes bases.

En effet le meilleur système pour le verrouillage est celui du TimeStamp. Personnellement
j'ai créé un système un peu plus évolué pour reproduire un peu la façon de faire de 4D avec
PHP et MySQL. Et c'est facilement mis en place, car générique.

Explications

1 - Un script PHP demande l'édition et le vérrouillage d'un enregistrement, je crée un identifiant unique pour le formulaire que je garde aussi dans un input caché du formulaire (plus loin il sera utilisé par un javascript). Je marque l'enregistrement dans la table concernée avec l'identifiant unique, et le timestamp de fin de vérrouillage (TimeStamp actuel + 5 minutes).

2 - Un script Javascript s'occupe depuis la page HTML qui contient le formulaire de faire une mise à jour
de ces valeurs dans l'enregistrement, il appelle toutes les 30 secondes un script de mise à jour qui va repousser le timestamp de 5 minutes (a condition que l'identifiant fourni soit le même que celui stocké dans l'enregistrement), ce qui permet de garder le verrouillage de manière indéfinie, tant que l'utilisateur a le formulaire affiché.

Deux cas sont géré aussi :

1 - L'utilisateur perd le formulaire (panne de courant, fermeture involontaire), il a 5 minutes pour le reprendre (redémarrer la machine et se reconnecter) car dans l'identifiant unique il y a aussi sont numéro d'utilisateur. Lorsque le serveur reçoit une nouvelle requête pour verrouiller l'enregistrement, il vérifie si l'utilisateur est le même, et si la dernière requête s'est produite il y a plus d'une minute.
Si les deux conditions sont remplies ou que l'enregistrement est toujours libre (non utilisé par quelqu'un d'autre entre deux) il donne un nouvel identifiant unique.

2 - Le script javascript reçoit la confirmation à chaque appel que son identifiant est toujours valable, si tel n'est pas le cas, il le masque (un simple changement de style CSS genre "document.getElementById('monformulaire').style.display='none';" et affiche un message. Cela protége non seulement d'une possible perte de connexion internet pendant plus de 5 minutes, mais aussi le fait qu'il ai pu charger l'enregistrement dans une autre fenêtre avec un autre identifiant. Dans ce dernier cas, c'est le dernier formulaire ouvert qui est valable. Ce cas est rare, mais il peut arriver, le cas concret, la connexion est perdue pendant 2 minutes avec le serveur, et elle réactivée avant que le javascript du formulaire en cours ai pu redemandé une mise à jour du timestamp. L'utilisateur peut dans ce laps de temps de quelques secondes ouvrir l'enregistrement dans une deuxième fenêtre.

Et ce qu'il ne faut pas oublié, c'est de supprimer tous les verrouillages fait par l'utilisateur une fois qu'il se déconnecte de ton application.

On peut même s'amuser en cas de perte de connexion avec le serveur de faire un message d'attente avec Javacript comme le fait 4D.

wow, je sais pas si j'ai été assez clair.

par webaida » 19 mai 2009, 08:39

Bonjour,

merci pour cet élément de réponse. En cherchant comment verrouiller un enregistrement, je suis bien tombé sur la doc de mysql, mais ce n'était pas explicitement marqué que ça ne pouvait pas correctement fonctionner en PHP.

L'idée du TS est intéressante, je pensais pour ma part gérer une table en parallèle dans laquelle écrire des informations, mais c'est sûrement plus simple comme tu proposes. Maintenant je suis un peu surpris, je pensais que comme le couple php/mysql était de plus en plus utilisé, des solutions moins "bricolées" étaient disponibles.

Je peux laisser le sujet ouvert pour avoir éventuellement d'autres réponses/façons de faire ?

Merci !

par zeus » 18 mai 2009, 19:06

Vu que PHP est un environnement en mode asynchrone, ça ne sera pas aussi simple que tu ne le faisais. :?
PHP s'exécute pour générer une page HTML, puis se termine. Il ne recommencera son exécution que lorsque tu lui demandera une autre page.
Tu vas avoir un problème majeur, c'est que tu seras incapable de savoir de manière sûr quand l'internaute quitte une page de modification (s'il ferme son navigateur, tu ne le sais pas)

Pour locker un enregistrement, ce qui se fait le plus souvent, c'est un système de réservation :
I) Demande de modification
Lorsque quelqu'un demande à modifier un enregistrement (demande le formulaire de modification), on met en base le timestamp actuel.
A partir de ce moment, l'utilisateur dispose de X minutes pour modifier l'enregistrements (où X est fixé par toi).

Maintenant, plusieurs cas de figures:
II a) Un autre utilisateur demande l'accès avant la fin des X minutes
Un second utilisateur demande à modifier l'enregistrement. Comme les X minutes de réservations ne sont pas terminées, tu indiques à ce second utilisateur qu'il ne peut accéder à la modification avant que l'autre valide, ou avant Y minutes (Y étant le temps restant avant la fin de la réservation)

II b) L'utilisateur valide son formulaire
Tu valides les données, tu les enregistres en base et tu effaces le timestamps. Tout le monde dispose à nouveau de la possibilité de le modifier

II c) Un autre utilisateur demande l'accès après la fin des X minutes
Tu fais comme si aucun verrou n'était en cours.


Bien évidemment, dans ce système, il faut que tu mettes un place un code JS qui informe celui qui a ouvert l'enregistrement 5mn, puis 1mn avant la fin de sa réservation, et lui dire que ses modifications ne seront pas prise en compte à la fin de la réservation

Mysql, lock et PHP

par webaida » 18 mai 2009, 17:37

Bonjour,

jusqu'à présent, je n'avais pas à vérifier que les enregistrements que je chargeais depuis ma base de données ne devaient pas être ouverts/modifiés par quelqu'un d'autre.

Je suis en train d'évaluer la possibilité de migrer d'un développement propriétaire (4D) vers un open source (php/mysql) et je bute sur un impératif : si un utilisateur charge une fiche client, tant qu'il ne l'a pas validé, aucun autre utilisateur ne doit la charger. Coté 4D, c'est géré automatiquement (+/-), qu'en est-il de (My)SQL ?

A priori, il faut que j'utilise "lock in share more", mais je n'arrive pas à comprendre comment ça peut fonctionner en PHP. Lorsque le script arrive à son terme, l'enregistrement est forcement libéré, non ?

En gros, si sur une page je charge les infos de l'enregistrement dans un formulaire, que l'utilisateur modifie (ou pas) ces données et qu'il soumet le formulaire, comment m'assurer que personne n'ai modifié l'enregistrement entre temps ?

Merci pour votre aide !