2009-01-28 7 views
5

Comment vérifier si un utilisateur a tapé le bon mot de passe pour se connecter?PHP & MySQL comparer mot de passe

C'est ce que (sur un tas de combinaisons ...) que je fais:

<? 

$login = $_POST['login']; 
$password = $_POST['password']; 

mysql_connect('localhost', 'root', 'abc123'); 

mysql_select_db('aun_vox') or die(mysql_error()); 

$q = mysql_query("SELECT password FROM customer WHERE login='$login'"); 
$db_pass = mysql_result($q, 0); 

if(md5($password) == $db_pass) 
{ 
    echo "You did it."; 
} 

else echo "Wrong."; 

?> 

Comme je peux voir de la ouput, il y a quelque chose de mal dans le peu mysql_result, mais je ne peux pas comprendre le bon chemin.

Quelqu'un peut-il m'aider s'il vous plaît.

+3

Nous avons ici à stackoverflow ne répondons pas aux questions sur les connexions. Nous préférons expliquer, en détail technique, comment désinfecter les entrées des utilisateurs. Il vaut mieux être sûr que d'avoir un site Web fonctionnel. – Grant

+5

@Grant: Vous plaisantez, non? –

+0

Soyez conscient que les réponses sur cette page sont obsolètes et donc dangereuses, jetez un coup d'œil à cette [question] (http://stackoverflow.com/q/4795385/575765) à la place. – martinstoeckli

Répondre

17

Je vois que vous stockez un hash du mot de passe dans la base de données, mais pour le bénéfice des autres lecteurs, jamais stocker les mots de passe en texte brut dans la base de données. Vous ne voulez pas être like Monster.com.uk!

Vous devez utiliser une fonction de hachage plus forte que MD5(). Idéalement, vous devriez utiliser SHA256. Cette méthode de hachage est disponible en PHP en utilisant la fonction hash().

Vous devez également appliquer un salt aléatoire au mot de passe. Stockez une valeur de sel différente pour le compte de chaque utilisateur. Cela permet de vaincre les attaques par dictionnaire et les attaques rainbow table.

Vous devriez apprendre à utiliser l'extension mysqli au lieu de l'ancienne extension mysql. Mysqli prend en charge les requêtes paramétrées, ce qui vous permet de réduire la vulnérabilité à certaines attaques par injection SQL.

Voici un exemple de code. Je ne l'ai pas testé, mais il devrait être assez proche de travail:

$input_login = $_POST['login']; 
$input_password = $_POST['password']; 

$stmt = $mysqli->prepare("SELECT password, salt FROM customer WHERE login = ?"); 
$stmt->bind_param("s", $input_login); 
$stmt->execute(); 
$stmt->bind_result($password_hash, $salt); 

while ($stmt->fetch()) { 
    $input_password_hash = hash('sha256', $input_password . $salt); 
    if ($input_password_hash == $password_hash) { 
    return true; 
    } 
    // You may want to log failed password attempts here, 
    // for security auditing or to lock an account with 
    // too many attempts within a short time. 
} 
$stmt->close(); 

// No rows matched $input_login, or else password did not match 
return false; 

D'autres personnes suggèrent que la requête doit tester login = ? AND password = ? mais je n'aime pas faire cela. Si vous faites cela, vous ne pouvez pas savoir si la recherche a échoué parce que la connexion n'existait pas ou parce que l'utilisateur a fourni un mot de passe incorrect.

Bien sûr, vous ne devriez pas révéler à l'utilisateur qui a causé la tentative de connexion échouée, mais vous besoin de savoir, de sorte que vous pouvez enregistrer une activité suspecte.


@Javier dit dans sa réponse que vous ne devriez pas récupérer le mot de passe (ou hachage de mot de passe dans ce cas) de la base de données. Je ne suis pas d'accord. Javier montre l'appel md5() dans le code PHP et l'envoi de la chaîne de hachage qui en résulte à la base de données. Mais cela ne permet pas de saler facilement le mot de passe. Vous devez faire une requête séparée pour récupérer le sel de cet utilisateur avant de pouvoir faire le hachage en PHP.

L'alternative est d'envoyer le mot de passe en texte brut sur le réseau de votre application PHP à votre serveur de base de données. Toute personne mettant sur écoute votre réseau peut voir ce mot de passe. Si vous avez des requêtes SQL enregistrées, toute personne ayant accès aux journaux peut voir le mot de passe. Les hackers motivés peuvent même faire de la benne à la recherche de vieux médias de sauvegarde du système de fichiers, et peuvent lire les fichiers journaux de cette façon!

Le moindre risque est de récupérer la chaîne de hachage du mot de passe de la base de données dans l'application PHP, de la comparer au hachage de l'entrée de l'utilisateur (également dans le code PHP), puis de supprimer ces variables.

+0

Il manquait juste une chose dans votre code. mysqli_prepare() prend deux paramètres - le premier étant le résultat de l'instruction mysqli_connect(). Comme j'utilisais mysql_connect() à la place, ça ne fonctionnait pas. Mais après la modification, ça fonctionne bien. Merci de votre aide. – Mussnoon

+0

Merci pour le crochet, je l'ai réparé. Cependant, je n'ai pas montré de connexion à la base de données. Je suppose que vous avez un objet $ mysqli en direct. –

+0

mysqli est trop horriblement bugg à utiliser (malheureusement) – cletus

1

quelques points:

  • Ne pas insérer les données de chaîne dans la chaîne de requête. En particulier les données fournies par l'utilisateur. que se passerait-il si je me connectais avec "Robert", drop table client "? Utilisez soit les routines d'échappement, soit (de loin) utilisez des instructions préparées et des paramètres de liaison. Ne stockez PAS les mots de passe en clair dans votre base de données.
  • (vous avez raison sur ce point)
  • Ne récupérez PAS les mots de passe de votre base de données.

ce que je fais habituellement est quelque chose comme:

$q = preparestatement ("SELECT id FROM customer WHERE login=? AND password=?"); 
bindvalue ($q, $_POST['login']); 
bindvalue ($q, md5($_POST['password'])); 
$id = execprepared ($q); 

if($id) { 
    echo "You did it."; 
} else { 
    echo "Wrong."; 
} 
+1

Nous l'appelons petites tables Bobby. – Powerlord

+3

Vous devriez probablement signaler que vous n'utilisez pas de code PHP natif ici. bindvalue() m'a fait un peu confus, et encore plus après ne pas l'avoir trouvé sur php.net. Enfin trouvé PHP Data Objects (PDO) en ligne qui a couvert les informations dans votre exemple. – Sampson

2

Tout d'abord, assurez-vous échapper à bien vos variables avant de les utiliser dans la requête - utilisation mysql_real_escape_string(). Puis, pourquoi ne pas utiliser la fonction MySQL MD5 pour vérifier une connexion valide dans votre requête? Ensuite, utilisez simplement mysql_num_rows() pour compter le nombre de lignes retournées.

0

Récupérer mot de passe de l'utilisateur de la méthode POST et FORM convertir $ _POST [ 'password'] // de la forme // en format approprié en php/jsp/tout autre puis comparer avec mot de passe dans votre base de données formaté

En général Le cryptage md5 est utilisé quand vous pouvez comparer md45 ('{$ _ POST [' mot de passe ']}') = présent dans votre db; ou généralement mysql utiliser mot de passe ('votre mot de passe') commande lors de la création du mot de passe donc d'abord votre $ _POST ['mot de passe] dans mysqli_query et mysqli_fetch_array pour obtenir la valeur du mot de passe crypté et ensuite comparer.

0

Supérieur à PHP 5.6, vous pouvez utiliser la fonction hash_compare.

$users_password = hash(sha256,$salt.$post_password); 

if (hash_equals($users_dbpassword, $users_password)) { 
     //pass is good 
} else { 
     // pass failed 
} 

http://php.net/manual/ru/function.hash-equals.php

+1

En fait, cette fonction ne doit pas être utilisée pour comparer les hachages de mots de passe (les hachages comparés ne sont pas adaptés aux mots de passe), utilisez plutôt [password_verify()] (http://www.php.net/manual/fr/function.password-verify. php) et générer le hachage avec [password_hash()] (http://www.php.net/manual/fr/function.password-hash.php). – martinstoeckli