[Tutorial] Systиme d'inscription et connection [MYSQL R39-3 - SHA256]
#1

[CENTER][SIZE="6"][COLOR="RoyalBlue"]Systиme d'inscription et connection [MYSQL R39-3 - SHA256][/COLOR][/SIZE]

[SIZE="5"][COLOR="RoyalBlue"]1- Introduction[/COLOR][/SIZE]

Bonjour, Bonsoir..
Je suis iзi aujourd'hui pour mon premier tutoriel.
J'ai remarquer que il n'y a pas beaucoup de tutoriels sur comment crйer un systиme d'inscription et connection utilisant MySQL dans la partie francophone.
Et beaucoup de franзais sur ce forum ne savent pas l'anglais.
Donc j'ai dйcidй d'en faire un ayant le plus de dйtails possibles.

[COLOR="RoyalBlue"][SIZE="5"]2- Besoins et intallations[/SIZE][/COLOR]

Pour faire ce systйme vous aurez besoin de:
- MySQL R39-3: https://github.com/pBlueG/SA-MP-MySQL/re.../tag/R39-3

Installer MySQL R39-3 et placй le dans son endroit respectif, c'est а dire le "mysql.dll" (ou "mysql.so") dans le dossier "plugins" et le "a_mysql.inc" dans le dossier "pawno>includes"

[COLOR="RoyalBlue"][SIZE="5"]3- Prйparation de la base de donnйes[/SIZE][/COLOR]

Il est l'heure de prйparer la base de donnйes celle oщ nous garderont les donnйes des joueurs!

Voiзi les choses а faire:[/CENTER]
  1. Sur phpMyAdmin: http://prntscr.com/8izw2f
    -
  2. Cliquer sur bases de donnйes
    -
  3. Crйer votre bases de donnйes: http://prntscr.com/8izwze
    -
  4. Maintenant que la bases de donnйes a йtй crйe on va crйe la Table qui comportera les donnйes des joueurs pour зela cliquer sur votre bases de donnйes!
    -
  5. Crйer la Table qui comportera 3 colonnes (L'ID de compte, Le nom et Le mot de passe): http://prntscr.com/8izzpz
    -
  6. Addiзioner les colonnes: http://prntscr.com/8j00rb (INT = Integer = Nombre entier / VARCHAR = Charactиre)
    [COLOR="Red"][Note: N'oubliez surtout pas de mettre Index 'PRIMARY' et de cocher A_I dans la colonne ID, A_I signifie "Auto Increment" permettant que le chiffre augmente de 1 a chaque nouvelle ligne, et PRIMARY permet de faire en sorte qu'il n'y ait pas de doublement de chiffre/nombre, rendant chaque nombre unique.][/COLOR]
[CENTER]
Et voilа notre base de donnйes est prкte. Nous pouvons commenзer a travailler sur le script.

[COLOR="RoyalBlue"][SIZE="5"]4- Cotй script[/SIZE][/COLOR]

On commenзe par le tout dйbut les Includes. Vous savez tous ce qu'est une include donc je n'est pas besoin d'expliquer.

[pawn]
#include <a_samp>
#include <a_mysql>
[/pawn]

Ensuite les Defines. Vous savez tous ce qu'est un define donc je n'est pas besoin d'expliquer.
On va definir le host, la base de donnйes, le compte et le mdp de MySQL pour qu'on puisse connecter notre serveur a la base de donnйes.

[pawn]
#define MYSQL_HOST "localhost"
#define MYSQL_COMPTE "root"
#define MYSQL_MDP ""
#define MYSQL_BDD "serveur"
[/pawn]

On va maintenant dйfinir les dialogues que l'on utilisera pour le systиme

[pawn]
#define DialogConnection 0
#define DialogInscription 1
[/pawn]

On va crйer maintenant l'enum oщ on va stockй temporairement, l'ID de compte, Le Nom du joueur et son Mot De Passe.

[pawn]
enum InfoJoueur
{
ID,
Nom[24],
MDP[66]
};
new iJoueur[MAX_PLAYERS][InfoJoueur];
[/pawn]

On crйe par la mкme occasion la variable globale qu'on utilisera pour definir notre base de donnйes.

[pawn]
new mysql;
[/pawn]

Alors maintenant on passe a "OnGameModeInit"
On ne vas pas seulement crйer les logs pour reзevoir les DEBUG, AVERTISSEMENT et ERREUR dans "mysql_log.txt", on va aussi connectй notre serveur a la base de donnйes, et par la mкme occasion on va verifier si on a rйussi a se connecter a la BDD.

[pawn]
public OnGameModeInit()
{
mysql_log(LOG_ALL); // Crйe les logs des Debugs, avertissements et erreurs.
mysql = mysql_connect(MYSQL_HOST, MYSQL_COMPTE, MYSQL_BDD, MYSQL_MDP); // Connecte le serveur a la base de donnйes
if(mysql_errno() != 0) // verifie si la connection a йtй rйussite
{
printf("[MySQL] Connection ratйe!");
}
else
{
printf("[MySQL] Connection rйussie!");
}
}
[/pawn]

On part maintenant dans "OnPlayerConnect" oщ on va vйrifier si le compte existe dйjа dans la base de donnйes!

[pawn]
public OnPlayerConnect(playerid)
{
TogglePlayerSpectating(playerid, true);
new requete[128], nom[24];
GetPlayerName(playerid, nom, sizeof(nom));
mysql_format(mysql, requete, sizeof(requete), "SELECT `Mot De Passe`, `ID` FROM `comptes` WHERE `Nom` = '%e' LIMIT 1", nom);
mysql_tquery(mysql, requete, "VerificationCompte", "i", playerid);
}
[/pawn]

Vous vous demandez quesque c'est ces SELECT, FROM, WHERE, LIMIT
Et bien s'est du language SQL, et oui vous qui vouliez crйer simplement un systйme de connection et inscription, vous кtes dйjа entrain d'apprendre et d'utiliser un nouveau language.

SELECT permet de sйlйctionner des rйsultats (dans ce cas Mot De Passe et ID)
FROM dйfini dans quelle table on va sйlйctionner ces rйsultats (dans ce cas dans la table "comptes")
WHERE permet de sйlйctionner les rйsultats d'une table oщ la condition correspond (dans ce cas oщ le Nom dans la BDD est йgal a celui du joueur)
LIMIT permet d'imposer une limite de rйsultats (dans ce cas une limite de 1 seul rйsultat)
Alors iзi On sйlйctionne "Mot De Passe" et "ID", de la table "comptes", oщ le "Nom" est йgal a celui du joueur et on ne veux que 1 seul rйsultat.

"mysql_format" fonctionne comme "format" mais comme vous le voyez, з'est pour MySQL seulement et il a 1 paramкtre en plus.
"mysql_tquery" envoie une requкte qui sera exйcutй dans un autre thread et appelle la callback (si elle existe) lorsque l'exйcution est terminйe.

[pawn]
forward VerificationCompte(playerid);
public VerificationCompte(playerid)
{
new lignes, champs;
cache_get_data(lignes, champs, mysql); // Assigne le nombre de lignes et champs trouver aprиs notre requete dans "OnPlayerConnect"
if(lignes) // Si la ligne qui correspond a notre requete existe
{
cache_get_field_content(0, "MDP", iJoueur[playerid][MDP], mysql, 66); // Transfиre le contenu de MDP de notre BDD et l'assigne а iJoueur[playerid][MDP]
iJoueur[playerid][ID] = cache_get_field_content_int(0, "ID"); // Transfиre le contenu de ID de notre BDD et l'assigne а iJoueur[playerid][ID]
ShowPlayerDialog(playerid, DialogConnection, DIALOG_STYLE_PASSWORD, "Connection...", "Tapez votre mot de passe pour vous connecter", "Connecter", "Quitter"); // On lui montre le dialogue de connection.
}
else // Si elle n'existe pas
{
ShowPlayerDialog(playerid, DialogInscription, DIALOG_STYLE_INPUT, "Inscription...", "Tapez un mot de passe pour inscrire ce compte.", "S'inscrire", "Quitter"); // On lui montre le dialogue d'inscription
}
}
[/pawn]

cache_get_data va assigner le nombre de lignes et de champs vers deux variables (lignes et champs).
Dans ce cas nous avons demandй 1 seul rйsultat, donc on va vйrifier si une ligne correspondante a йtй trouvйe aprиs notre requete en utilisant "if (lignes)"

cache_get_field_content va vous aider a prendre d'un certain champ son contenu, et va ensuite l'assigner quelque part, example: une variable, ou dans notre cas un enum.

cache_get_field_content_int marche diffйremment mais c'est pour faire la mкme chose avec les entiers et non pas avec les charactиre. Vous pouvez voir comment il fonctionne dans le code.

Et ShowPlayerDialog vous devez savoir ce que c'est, donc je n'ai pas besoin de vous expliquer.

Bon maintenant nous allons travailler sur notre dialogue d'inscription pour cela on passe a la callback "OnDialogResponse"

[pawn]
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
switch(dialogid)
{
case DialogInscription:
{
if(!response) return Kick(playerid); // Si le joueur clique sur "Quitter" on va la Kicker du serveur
if(strlen(inputtext) < 5) // Si le MDP insйrй fais moins de 5 charactиres
{
SendClientMessage(playerid, -1, "Votre mot de passe doit contenir au moins 5 charactиres"); // On lui envoye un message disant que le MDP doit contenir au moins 5 charactиres.
ShowPlayerDialog(playerid, DialogInscription, DIALOG_STYLE_INPUT, "Inscription...", "Tapez un mot de passe pour inscrire ce compte.", "S'inscrire", "Quitter"); // On lui remontre le dialogue.
}
else // Si le MDP insйrй contient au moins 5 charactиres
{
new requete[512], hashpass[64+1], Nom[24];
GetPlayerName(playerid, Nom, sizeof(Nom));
SHA256_PassHash(inputtext, "ADAWAD11AWD41ASDA2L222KDH", hashpass, sizeof(hashpass));
mysql_format(mysql, query, sizeof(query), "INSERT INTO `comptes` (`Nom`, `Mot De Passe`) VALUES ('%e', '%e')", Nom, hashpass);
mysql_tquery(mysql, query, "CreationCompte", "i", playerid);
}
}
[/pawn]

Et oui il y'a de nouvelles fontions SQL, INSERT INTO et VALUES
INSERT INTO permet d'insйrer/crйer une nouvelle ligne dans une table.
VALUES sont les contenus de chaque champs dans la ligne. (Sachant que vous pouvez en laisser vides.)
Dans ce cas nous insйrons une nouvelle ligne dans la table comptes avec les contenus Nom = Nom du joueur et Mot De Passe = HashMDP
Pourquoi HashMDP et non pas le MDP directement?
HashMDP est le nom que l'on a donner au hash de SHA256_PassHash.

[SIZE="3"]Quesque SHA256_PassHash?[/SIZE]
SHA256_PassHash permet de hasher quelque chose, et en mкme temps met un salt.

[SIZE="3"]Quesque "hasher"?[/SIZE]
FS4F654SQ31S3F4DS8F34DG3DF4G3D4SD86G4G3D5SQG34G3FD51, зeзi est un hash.
Pour expliquer un hash est une sйrie de chiffres et lettres crйe au hasard.
Mais pas totalement au hasard.

[SIZE="3"]Pourquoi hasher les MDP?[/SIZE]
Pour la sйcuritй de vos joueurs, si un jour votre BDD est hacker les hackeur ne pourront pas voir les MDP a cause du hash. Et les MDP de vos joueurs seront donc sйcurisйs. Sachant que 80% des joueurs utilisent le mкme MDP pour tout, ********, SAMP, Paypal etc..

[SIZE="3"]Pourquoi [COLOR="Red"]NE PAS[/COLOR] simplement hasher les MDP?[/SIZE]
Oui le hashing protиge vos MDP comme vous le voyez, mais pas totalement!
Le hashing comme je l'ai dit en haut est une sйrie de chiffres et lettres crйe au hasard. Mais j'ai aussi dit "Mais pas totalement au hasard."
Pourquoi?
Car le hashing n'est pas vraiment au hasard, le hashing est une sйrie de chiffres et lettres crйe oui, mais chaque lettres а son propre hashing. Si on crйer un dictionnaire, et bien on va ajouter "123" et sa valeur hashйe et on peux alors essayer de comparer la valeur hashйe avec le mot de passe volй.
C'est la que le "Salt" entre en scиne.

[SIZE="3"]Quesque un "salt"?[/SIZE]
Tout comme le hash le salt est une sйrie de chiffres et lettres crйe au hasard.
Mais dans le salt, les lettres crйe sont vraiment au hasard, зe qui rent les MDP quasi impossible de dechifrer!

Bon continuons avec la crйation de la callback "CreationCompte"

[pawn]
forward CreationCompte(playerid);
public CreationCompte(playerid)
{
iJoueur[playerid][ID] = cache_insert_id(); // On prend l'ID de compte du joueur et on l'insиre dans iJoueur[playerid][ID]
printf("[Inscription] Nouveau comptes inscris. ID de compte: [%d]", iJoueur[playerid][ID]);
TogglePlayerSpectating(playerid, false); // On enlиve le joueur de spec
SpawnPlayer(playerid); // On spawn le joueur
return 1;
}
[/pawn]

cache_insert_id sert a rйcupиrer l'ID gйnйrй pour une colonne A_I par la derniиre requкte envoyйe.
Donc iзi on prend le dernier ID gйnйrй (celui de l'inscription), on l'insиre dans iJoueur[playerid][ID] et ensuite on fait un print disant qu'un nouveau compte a йtй inscrit et on montre l'ID du compte.

Bon nous avons fini avec l'inscription, nous allons maintenant passer a la connection.

Nous avons dйjа fait le code qui permet de verifiй si le compte existe, donc on va commenзer directement par le dialogue

On va donc dans "OnDialogResponse" et en dessous du dialogue d'inscription on ajoute:

[pawn]
case DialogConnection:
{
if(!response) return Kick(playerid); // Si le joueur appuie sur "Quitter" on le Kick du serveur.
new hashpass[64+1];
SHA256_PassHash(inputtext, "ADAWAD11AWD41ASDA2L222KDH", HashMDP, sizeof(HashMDP));
if(!strcmp(HashMDP, iJoueur[playerid][MDP], true)) // Si le MDP insйrй est йgal au MDP de la BDD
{
new requete[100];
mysql_format(mysql, requete, sizeof(requete), "SELECT * FROM `comptes` WHERE `Nom` = '%e' LIMIT 1", Nom); // On prend la ligne ou le nom est йgal au nom du joueur
mysql_tquery(mysql, requete, "ChargerCompte", "i", playerid); // On envoye la requete.
}
else // Si le MDP insйrй n'est pas йgal au MDP de la BDD
{
SendClientMessage(playerid, -1, "Mot de passe incorrect, essayer encore!"); // On envoie le message disant que le MDP est incorrect!
ShowPlayerDialog(playerid, DialogConnection, DIALOG_STYLE_PASSWORD, "Connection...", "Tapez votre mot de passe pour vous connecter", "Connecter", "Quitter"); // On lui remontre le dialogue
}
}
return 1;
}
[/pawn]

Donc vous voyez que au lieu d'y avoir un champ aprиs SELECT, il y a un *
* = Tout
Donc on prend tous les champs dans comptes oщ le Nom est йgal a celui du joueur.

Donc on va continuez avec la crйation de la callback "ChargerCompte" avec laquelle on va donnй au joueur ses donnйes.

[pawn]
forward ChargerCompte(playerid);
public ChargerCompte(playerid)
{
TogglePlayerSpectating(playerid, false); // On enlиve le joueur de spec
SpawnPlayer(playerid); // On spawn le joueur
SendClientMessage(playerid, -1, "Vous кtes maintenant connectй et vous pouvez jouer tranquillement.");
iJoueur[playerid][Argent] = cache_get_field_int(0, "Argent"); // Nous envoyons l'argent vers iJoueur[playerid][Argent]
GivePlayerMoney(playerid, iJoueur[playerid][Argent]);
return 1;
}
[/pawn]

Bon aprиs кtre arrivй a ce stade du tutoriel, je me suis rendu compte que j'aurais du utilisй des exemples, comme L'argent ou le Score.. Ce que je n'ait pas fait.. Excusez-moi, donc nous allons faire comme si nous avions mis 'Argent' dans la BDD.

Donc nous utilisont cache_get_field_int pour assigner iJoueur[playerid][Argent] l'argent et ensuite on le donne au joueur en utilisant GivePlayerMoney.

Et voilа nous avons fini avec la connection.

Mais comment sauvegarder les donnйes dans la BDD?

On va l'apprendre maintenant.

On part dans "OnPlayerDisconnect"

[pawn]
public OnPlayerDisconnect(playerid)
{
new requete[128];
mysql_format(mysql, requete, sizeof(requete), "UPDATE `comptes` SET `Argent` = %d WHERE `ID` = %d",
GetPlayerMoney(playerid), pInfo[playerid][ID]);
mysql_tquery(mysql, requete, "", "");
}
[/pawn]

Alors nous voyons WHERE on as apris а quoi il sert en haut, mais il y a 2 nouvelles fonctions, UPDATE et SET
UPDATE permet de changer quelque chose dans une table.
SET permet de changer cette chose

Dans ce cas on change le contenu de Argent dans la table comptes oщ l'ID est йgal a l'ID de compte du joueur

[COLOR="RoyalBlue"][SIZE="5"]5- La fin[/SIZE][/COLOR]

Bon nous avons fini le systиme

J'йspиre vous avoir aider avec ce tutoriel, et je suis vraiment dйsoler pour ne pas avoir mis des exemples comme des float ou quoi.. Sur ce je vous laisse!

Bonne Journйe/Bonne Nuit.
[/CENTER]
Reply
#2

Je crois que зa a dйjа йtй fait comme tuto, m'enfin tout travail mйrite salaire, puis c'est plutфt bien d'avoir plusieurs tuto et mйthodes pour le mкme systиme +rep :)
Reply
#3

Merci beaucoup, ce tutoriel ma super bien aidй pour mon manque de compйtence en SQL.

par-contre j'ai un souci, lorsque je tente de me connecter il me dit que mon MDP est erronй, dans la BDD il est bien cryptй pourtant, j'ai suivi а la lettre ton tutoriel.

Merci de ta rйponse.
Reply
#4

Autant pour moi j'avais limitй le nombre de caractиres а 24 au lieu de 66. Forcйment le cryptage est plus йlevй.
Problиme rйsolu.

Tu saurais comment rйinitialiser dans la BDD l'id ? Car j'ai supprimй tous les comptes et l'AI continue tout de mкme malgrй qu'il n'y a plus de compte.
Reply
#5

Tu va dans ton phpMyAdmin et tu appuie sur "SQL" et puis tu йcris:
"ALTER TABLE NomDeTaTable AUTO_INCREMENT = 1"

Note: Les comptes doivent кtre supprimйs avant.
Reply
#6

Merci :)
Reply
#7

Salut c'est cool par contre:

Avec une table qui dйchifre le hashing de chaque lettre il est possible de trouver le MDP.
C'est la que le "Salt" entre en scиne.

C'est faux (ou mal expliquer). Le truc c'est par exemple si on crйer un dictionnaire (et certain existe), et bien on va ajouter "123" et ca valeur hasher et on peux essayer de comparer la valeur hasher avec le mot de passe volй. Alors que si on hash "123.myserver" bah ils ne trouverons jamais le mot de passe.
Reply
#8

92izi;3588165 Wrote:Salut c'est cool par contre:

Avec une table qui dйchifre le hashing de chaque lettre il est possible de trouver le MDP.
C'est la que le "Salt" entre en scиne.

C'est faux (ou mal expliquer). Le truc c'est par exemple si on crйer un dictionnaire (et certain existe), et bien on va ajouter "123" et ca valeur hasher et on peux essayer de comparer la valeur hasher avec le mot de passe volй. Alors que si on hash "123.myserver" bah ils ne trouverons jamais le mot de passe.

Merci a toi je viens d'йditer le topique!
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)