JeuWeb - Crée ton jeu par navigateur
Module d'identification - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : Module d'identification (/showthread.php?tid=917)

Pages : 1 2


Module d'identification - NicoMSEvent - 22-12-2010

Ce tutorial est la suite du Module d'inscription

Maintenant qu'on a un joueur inscrit, il faudrait faire en sorte qu'il puisse s'identifier

Lorsqu'il s'identifie, il entre son adresse e-mail (par exemple, ça aurait pu être son nom), et son mot de passe.

Il faut vérifier que ces deux données sont justes. Mais comment vérifier un mot de passe crypté, et donc indéchiffrable? Rien de plus simple! On va crypter le mot de passe entré par le joueur, et vérifier que les deux données cryptées sont identiques. Si elle ne le sont pas, alors le mot de passe donné maintenant ne correspond pas au mot de passe entré lors de l'inscription.

ça donne ceci en SQL


SELECT id,nom FROM joueurs WHERE email='%s' AND motdepasse=PASSWORD('%s')

Pour le formulaire en HTML, c'est facile, vous pouvez adapter celui du tutorial précédent, ce qui donnerais ceci :

<form action="identification.php" method="post">
E-mail<input name="email" type="text" />
Mot de passe<input name="motdepasse" type="password" />
<input type="submit" />
</form>

Et biensur le code PHP qui va récupérer tout ça

<?php
session_start(); //on va utiliser une session dans notre script
if( isset($_SESSION['id_joueur']) ){
$sql=sprintf("SELECT id,nom FROM joueurs WHERE id='%s' ",$_SESSION['id_joueur']);

//on se connecte a la base de donnée (oui, il faut le refaire a chaque nouvelle page)
$db = mysql_connect ("mon_serveur_sql", "mon_login", "mon_mot_de_passe");
$req=mysql_query($sql,$db);

//maintenant, on va parcourir la liste des résultats
while( $res=mysql_fetch_assoc($req) ){
$cpt++;
}
echo "Joueur : ".$res['nom']." déjà connecté<br/>";
}
else{
$email=mysql_real_escape_string($_POST['email']);
$motdepasse=mysql_real_escape_string($_POST['motdepasse']);

$sql=sprintf("SELECT id,nom FROM joueurs WHERE email='%s' AND motdepasse=PASSWORD('%s')",$email,$motdepasse);

//on se connecte a la base de donnée (oui, il faut le refaire a chaque nouvelle page)
$db = mysql_connect ("mon_serveur_sql", "mon_login", "mon_mot_de_passe");
$req=mysql_query($sql,$db);

$cpt=0;
//maintenant, on va parcourir la liste des résultats
while( $res=mysql_fetch_assoc($db) ){
$cpt++;
}

//si il y a un résultat, l'utilisateur exsite et a le bon mot de passe
if($cpt>0){
echo "Bienvenue ".$res['nom']; //je récupère la valeur de la colonne "nom" indiqué dans le SELECT
$_SESSION['id_joueur']=$res['id']; //je garde en SESSION l'identifiant unique du joueur
}
else{
echo"adresse e-mail ou mot de passe erroné";
}
}
?>

Qu'est-ce qu'une session? C'est une variable enregistrée sur le serveur, et qui va suivre le joueur tout au long de son parcours. Elle est en général liée à un COOKIE sur le navigateur. C'est a dire que si le joueur supprime ses cookies, il ne sera plus connecté.

L'avantage de garder l'identifiant sur le serveur, est qu'on ne peut pas le bidouiller, contrairement aux COOKIES.

Principe de sécurité de base, ne pas faire confiance a ce qui vient directement du joueur, c'est a dire ce qui vient des sources suivantes : $_GET, $_POST, $_COOKIE, $_REQUEST, ... (il y en a certainement d'autres, mais de tête les plus importantes sont celles là), il faut toujours vérifier que ce soit valide (injection de SQL, de HTML, de Javascript, bidouillage des URL, des COOKIES, ...)!!!

Par contre, les variables du coté serveur sont elles moins sujette à ce genre de bidouillages : $_SESSION, et toutes les autres variables déclarées dans vos scripts.

N'oubliez pas d'initialiser vos variables!!! Certaines configurations peuvent présenter de gros risques, et l'oubli de l'initialisation peut être fatal en cas de mauvaise configuration!

Pour se déconnecter, voilà le script PHP qui va le faire :

<?php
session_destroy();
?>

C'est tout? C'est aussi simple que ça?
Oui! Il suffit de "perdre" la donnée de session, et ça suffit Smile

Pour sécuriser un peu plus votre application (session?), voilà un lien qui propose quelques pistes : sécurité sur Developpez.com


RE: Module d'identification - Jeckel - 22-12-2010

Attention, tu utilises la session sans l'avoir initialiser...

Ensuite le unset($_SESSION['id_joueur']); c'est dangereux, tu peux laisser des choses dans la session qui vont venir perturber le joueur s'il se reconnecte...

Je préfère un véritable session_destroy


RE: Module d'identification - NicoMSEvent - 22-12-2010

ok, merci pour le coup de main, je corrige au fur et à mesure Smile


RE: Module d'identification - Globe - 22-12-2010

Je ne connais la fonction sprintf et je trouve que le manuel est pas hyper clair, ça sert à éviter que la chaîne soit modifiée par des paramètres extérieurs ?


RE: Module d'identification - Blarg - 22-12-2010

Un petit détail, ne faudrait t'il pas ajouter ce petit bout de code lorsque le serveur reconnait une session?


if($cpt>0){
echo "Joueur : ".$res['nom']." déjà connecté";
}
else{
echo"session refusée...";
}
Au cas où le joueur manipule ses cookies identifiant sa session?


RE: Module d'identification - NicoMSEvent - 22-12-2010

@Blarg : pour bidouiller les identifiants de session, il faut avoir la bonne chaine (32 char?), qui est aléatoirement donnée au visiteur. On ne saurait que "voler" la session de quelqu'un d'autre a condition que cette personne soit restée connectée (pas de déco explicite lorsqu'il quitte le jeu)

De plus, comme le login(email)/mot de passe ne sont pas stockés dans le cookie (ni dans la session), impossible de les voler.

On ne saurait pas changer l'identifiant du joueur qui est stocké coté serveur (dans la session), je ne comprends pas pourquoi tu t'inquiète pour ça
Il n'y arait pas une confusion entre identifiant du joueur(clé primaire), et identifiant de session(chaine aléatoire de 32char)? Wink

Je ne comprends pas pourquoi tu teste dans ce morceau de code l'utilisateur déjà connecté, puisque dans cette portion, l'utilisateur n'est en principe pas connecté. Et si il n'est déjà, on n'a pas de moyen de le savoir sans ajouter l'adresse IP, ou une autre information (identifiant de session?) qui n'est pas prévue dans cet exemple.

Je tiens a rester le plus simple possible afin que les principes de base soit compris, ici je n'apprends pas la sécurité avancée (qui fera l'objet d'un futur tutorial), ni les cas trop spécifiques Smile


RE: Module d'identification - Ter Rowan - 22-12-2010

question d'ingénu côté sécurité

je ne comprends pas à quoi sert l'appel en bdd lorsque la session existe :

est pour capter des informations pour la suite ou pour des raisons de sécurité ?

parce que je ne vois pas de sécurité dans cette première partie

si je chope la session (par un hasard heureux d'un autre), j'envoie cet id (de session), le système tel que je le lis va me reconnaitre comme étant le joueur de la session "volée"


ou bien je suis à côté de la plaque


RE: Module d'identification - niahoo - 22-12-2010

(22-12-2010, 02:53 PM)Globe a écrit : Je ne connais la fonction sprintf et je trouve que le manuel est pas hyper clair, ça sert à éviter que la chaîne soit modifiée par des paramètres extérieurs ?

non ça sert simplement à formater ses chaînes plus lisiblement.

(sprintf('%s je m\'appelle %s et j\'ai %d ans', 'bonjour', $prenom, $age))
== 'bonjour'.je m\'appelle '.$prenom.' et j\'ai '.$age.' ans';

mais sprintf te permet plus de manipulations qu'une simple concatenation car souvent tu feras

sprintf(LANG_HELLO, 'bonjour', $prenom, $age);

et dans la constante LANG_HELLO tu peux choisir dans quel ordre apparaissent les autres arguments passés.

edit: hmmm le module de coloration en chie un peu ! :p


RE: Module d'identification - Myrina - 22-12-2010

Il y a quand même des choses qui ne vont pas! :nonon:

En utilisant l'extension mysql, tu aurais pu écrire

if (mysql_num_rows($req)>0) {
$res=mysql_fetch_assoc($req);
...
}
au lieu de:

$cpt=0;
//maintenant, on va parcourir la liste des résultats
while( $res=mysql_fetch_assoc($db) ){
$cpt++;
}

//si il y a un résultat, l'utilisateur exsite et a le bon mot de passe
if($cpt>0){

de plus, le paramètre de mysql_fetch_assoc() est $req et non $db.

par ailleurs, ton id en table est un entier, pas une chaine de caractères:

$sql=sprintf("SELECT id,nom FROM joueurs WHERE id='%s' ",$_SESSION['id_joueur']);
devrait être

$sql=sprintf("SELECT id,nom FROM joueurs WHERE id=%i ",intval($_SESSION['id_joueur']));

Maintenant, il reste un problème de logique de conception sans parler de la gestion d'erreurs.
Code :
si joueur deja identifié en session
alors
- recherche des informations le concernant
- si les informations existe
- alors "bonjour joueur"
- sinon erreur!!
sinon
- si le formulaire est correctement rempli
---- vérification des informations de connexion (authentification)
---- si ok
-------- sauvegarde en session de l'identifiant du joueur
---- sinon
-------- erreur d'authentification
- sinon erreur de saisie du formulaire



RE: Module d'identification - NicoMSEvent - 22-12-2010

(22-12-2010, 03:28 PM)Ter Rowan a écrit : je ne comprends pas à quoi sert l'appel en bdd lorsque la session existe :
est pour capter des informations pour la suite ou pour des raisons de sécurité ?
pour retrouver le nom du joueur, et ajouter éventuellement d'autres choses par la suite, comme le score par exemple
(22-12-2010, 03:28 PM)Ter Rowan a écrit : parce que je ne vois pas de sécurité dans cette première partie

si je chope la session (par un hasard heureux d'un autre), j'envoie cet id (de session), le système tel que je le lis va me reconnaitre comme étant le joueur de la session "volée"

ou bien je suis à côté de la plaque
Tu as tapé juste, il suffit de choper l'identifiant de session pour faire croire que tu es cet utilisateur. Comme expliqué, je ne traite que très peu de sécurité, je donne les bases pour créer ce module Wink

(22-12-2010, 03:36 PM)Myrina a écrit : Il y a quand même des choses qui ne vont pas! :nonon:

En utilisant l'extension mysql, tu aurais pu écrire

if (mysql_num_rows($req)>0) {
$res=mysql_fetch_assoc($req);
...
}
au lieu de:

$cpt=0;
//maintenant, on va parcourir la liste des résultats
while( $res=mysql_fetch_assoc($db) ){
$cpt++;
}

//si il y a un résultat, l'utilisateur exsite et a le bon mot de passe
if($cpt>0){
je garde cette structure pour un parcours des différents enregistrement. Si $res est null (ou 0 ou false), il n'y a pas (plus) d'enregistrement. Si je donne cette structure, pour éviter de donner trop de fonctions d'un coup, et garder une sorte d'unité dans tous mes appels a la DB. Faut pas noyer les novices dès le début Wink

(22-12-2010, 03:36 PM)Myrina a écrit : de plus, le paramètre de mysql_fetch_assoc() est $req et non $db.
corrigé ... faute d'inattention Wink

(22-12-2010, 03:36 PM)Myrina a écrit : par ailleurs, ton id en table est un entier, pas une chaine de caractères:

$sql=sprintf("SELECT id,nom FROM joueurs WHERE id='%s' ",$_SESSION['id_joueur']);
devrait être

$sql=sprintf("SELECT id,nom FROM joueurs WHERE id=%i ",intval($_SESSION['id_joueur']));
en effet, pour plus de simplicité, je traite tout comme des chaines de caractère (pas de traitement d'erreur pour encore une fois rester le plus simple possible)

(22-12-2010, 03:36 PM)Myrina a écrit : Maintenant, il reste un problème de logique de conception sans parler de la gestion d'erreurs.
Code :
si joueur deja identifié en session
alors
- recherche des informations le concernant
- si les informations existe
- alors "bonjour joueur"
- sinon erreur!!
sinon
- si le formulaire est correctement rempli
---- vérification des informations de connexion (authentification)
---- si ok
-------- sauvegarde en session de l'identifiant du joueur
---- sinon
-------- erreur d'authentification
- sinon erreur de saisie du formulaire
Pour la logique, je pense etre resté simple. je ne prévois pas tous les cas

Citation :si joueur deja identifié en session
alors
- recherche des informations le concernant
- si les informations existe
- alors
"bonjour joueur"
- sinon erreur!!
Quel intérêt puisque l'identifiant stocké en session est valide (testé lors du premier passage), et que j'estime qu'il ne sera pas supprimé entre la connexion et le test ici
sinon
- si le formulaire est correctement rempli
---- vérification des informations de connexion (authentification)
---- si ok
-------- sauvegarde en session de l'identifiant du joueur
---- sinon
-------- erreur d'authentification
- sinon erreur de saisie du formulaire

J'aime ton esprit critique, même si parfois je pense que tu cherches un peu loin Wink