feanor13 Posté 27 Avril 2009 Posté 27 Avril 2009 Salut à tous, Je suis entrain de créer un système anti-bruteforce et pour cela j'ai besoin de verrouiller un fichier en accès exclusif. Jusque-là, aucun problème. Mais je veux aussi que si une deuxième requête veut accéder à ce fichier alors que celui-ci est verrouillé, la fonction "flock" n'attende pas que le fichier se déverrouille (comme c'est le cas par défaut) mais renvoie une erreur. J'ai donc mis le 3ème paramètre de "flock" à false, mais cela ne fonctionne pas car quand je teste de lancer 2 requête simultanées (avec un sleep suffisamment grand) la 2ème requête attend que la première ait terminée pour s'exécuter. Je vous donne mon code simplifié: <?php$fichier_tentatives = fopen('antibrute/'.$_POST['pseudo'].'.tmp', 'r+');$block = false;// pose un verrou exclusifif(flock($fichier_tentatives,LOCK_EX, $block)){//opération à effectuer ...sleep(10);}else{exit("Vous ne pouvez pas lancer deux tentatives de connexion simultanément. Réessayez plus tard.");}?> Merci d'avance et @+ !
jcaron Posté 27 Avril 2009 Posté 27 Avril 2009 Tu n'as pas bien lu la doc... Pour que ça ne bloque pas, il faut passer LOCK_NB en deuxième argument (en plus du LOCK_EX, donc LOCK_EX | LOCK_NB). Le troisième argument doit être une référence à une variable qui indiquera si le lock aurait bloqué en l'absence de LOCK_NB, ce qui est redondant avec la valeur de retour de flock et errno a priori... Voir http://us3.php.net/manual/en/function.flock.php#90547 pour un exemple. Jacques.
feanor13 Posté 28 Avril 2009 Auteur Posté 28 Avril 2009 (modifié) Salut, Merci pour l'exemple, mais cela ne fonctionne toujours pas. Voilà mon code: <?php$fichier_tentatives = fopen('antibrute/'.$_POST['pseudo'].'.tmp', 'r+');// pose un verrou exclusifif(flock($fichier_tentatives, LOCK_EX | LOCK_NB)){sleep(10);flock($fichier_tentatives, LOCK_UN); // libère le verroufclose($fichier_tentatives);}else{exit("Vous ne pouvez pas lancer deux tentatives de connexion simultanément. Réessayez plus tard.");}?> Je précise que même si je spécifie le paramètre optionnel à false cela ne fonctionne pas. Merci d'avance et @+ Modifié 28 Avril 2009 par feanor13
jcaron Posté 29 Avril 2009 Posté 29 Avril 2009 (modifié) Petit problème dans ton fopen, tu ouvres en "r+", il faut que le fichier existe déjà pour que ça marche. Passe en "w" par exemple pour qu'il soit créé à la demande. Note aussi que comme indiqué dans la doc, flock et NFS ne font pas bon ménage. Ce qui veut dire que chez beaucoup d'hébergeurs, en mutualisé et autres solutions ou le disque dur n'est pas local, ça ne marchera pas. Ce qui d'ailleurs me fait penser qu'il y a encore plus simple: fais juste un fopen en "x" et teste la valeur de retour. Si le fichier n'existe pas, il sera créé, et tout va bien. Si le fichier existe déjà, tu auras une erreur. Evidemment il faut penser à supprimer le fichier une fois que tu as fini (avec unlink). $lock_filename='/var/tmp/antibrute_'+$pseudo;$lock_fh=fopen($lock_filename,'x');if ($lock_fh){ // tout va bien, faire traitement fclose($lock_fh); unlink($lock_filename);}else{ // lock déjà pris} Inconvénient avec cette méthode: s'il y a un problème en cours de route et que le fichier reste, le pseudo en question sera bloqué jusqu'à suppression manuelle du fichier. Au passage, le nom de fichier qui utilise directement un $_POST['whatever'] c'est très très très dangereux... Si le gars il met des "/" et des ".." il peut casser toutes sortes de choses. Donc bien vérifier/nettoyer avant d'utiliser. Jacques. EDIT: ajout incompatibilité avec NFS. Modifié 29 Avril 2009 par jcaron
feanor13 Posté 29 Avril 2009 Auteur Posté 29 Avril 2009 Salut, le problème doit donc venir de l'hébergeur. Merci pour cette précision. Par contre ta technique ne me convient pas car elle ne me permet pas de sauvegarder le nombre de tentatives de connexion (car il s'agit d'un script de connexion) car le fichier est supprimé après chaque tentative et je ne peux donc pas avertir l'administrateur par mail. Je voulais verrouiller pour éviter que deux requêtes puissent accéder au même fichier. Je pense donc que au lieu de verrouiller, je vais faire comme ceci: A chaque fois qu'une requête sera lancée, j'ouvrirai le fichier, mettrai une valeur à 1 et lorsque l'entier de ma requête sera traité (sleep y compris), je remettrai cette valeur à 0. De plus lorsqu'une requête tentera d'accéder à un fichier, elle vérifiera d'abord que la valeur soit bien à 0, dans le cas contraire je mets un exit(). Que pensez-vous de ma technique ? Des conseils ou améliorations ? Merci et @+
jcaron Posté 29 Avril 2009 Posté 29 Avril 2009 Je ne comprends pas tout... Le but du jeu c'est juste d'empêcher deux personnes de faire la même chose en même temps? Tu crées le fichier de lock au début du traitement, et tu le supprimes quand tu as fini, ça revient exactement au même que les autres méthodes, et c'est plus simple. Ou j'ai raté un truc? Jacques.
feanor13 Posté 29 Avril 2009 Auteur Posté 29 Avril 2009 (modifié) En fait, dans le fichier de lock, j'enregistre aussi le nombre de tentatives pour que à 30 tentatives un email soit automatiquement envoyé à l'administrateur. Je ne supprime donc jamais le fichier. Je contrôle qu'il est à jour: si oui, j'incrémente le fichier, sinon je mets à jour le fichier. Ce système permet à l'administrateur de prendre des mesures si le quota est dépassé plusieurs fois de suite (par exemple demander au membre de changer son mot de passe). En rajoutant une variable à l'intérieur de mon fichier pour savoir si il est en cours d'utilisation ou non, cela me permet de garder un système (relativement) simple tout en conservant le maximum de fonctionnalités et sans utiliser trop de ressources. Les autres avantages sont que si il y a interruption, au pire deux requêtes pourront être lancées simultanément mais la connexion ne sera pas bloqué comme avec ton système. Pour la variable $_POST['pseudo'], ne t'en fais pas, je l'ai sécurisée. C'est juste que j'ai mis un extrait de code. Ce serait trop long sinon ! Donc la méthode "w" ne va pas car elle efface le contenu du fichier. Alors que penses-tu de ma méthode ? N'hésites pas à me demander des précisions et à faire des suggestions (je suis débutant et preneurs de tout conseils). Merci à toi et @+ Modifié 29 Avril 2009 par feanor13
Sujets conseillés
Veuillez vous connecter pour commenter
Vous pourrez laisser un commentaire après vous êtes connecté.
Connectez-vous maintenant