web-dev-qa-db-fra.com

php password_verify ne fonctionne pas avec la base de données

J'utilise php 5.4 avec ce script de compatibilité descendante: https://github.com/ircmaxell/password_compat/blob/master/lib/password.php

cela ne devrait pas avoir d'importance, car je peux faire fonctionner le processus de hachage et de vérification dans ma fonction d'enregistrement:

$hash = password_hash($pass, PASSWORD_DEFAULT);

echo $pass;
echo $hash;

if( password_verify($pass,$hash) )
    echo 'success';
else echo 'failure';

//success is always shown

//EXAMPLE INPUT
$pass = 'password';

//EXAMPLE OUTPUT
password$2y$10$JK1jumvvSIm/gP3fWE3k9O98MzvHKDRYCjRPBniYg9riACyQw7WYSsuccess

mais chaque fois que j'essaie de stocker le hachage dans une base de données MySQL, puis de le récupérer pour la fonction de vérification, il échoue toujours. Voici ma fonction de connexion:

function user_login( $mysqli, $email, $pass ){    

        $err_msg = 'login: '.$mysqli->error.' | '.$email;

        if( $stmt = $mysqli->prepare('SELECT password FROM users WHERE email=?') ) :

            if( !$stmt->bind_param('s', $email) ) log_sql_error( $err_msg );
            if( !$stmt->execute() ) log_sql_error( $err_msg );
            if( !$stmt->bind_result( $hash ) ) log_sql_error( $err_msg );
            if( $stmt->fetch() === FALSE ) log_sql_error( $err_msg );
            if( !$stmt->close() ) log_sql_error( $err_msg );

            //I can see that these values are identical to the ones
            //echoed out in the registration function
            echo $pass;
            echo $hash;

            if( password_verify($pass,$hash) )
                echo 'success';
            else echo 'failure';

        else : log_sql_error( $err_msg );
        endif;
}
//failure is always shown

//EXAMPLE INPUT
$pass = 'password';

//EXAMPLE OUTPUT
password$2y$10$JK1jumvvSIm/gP3fWE3k9O98MzvHKDRYCjRPBniYg9riACyQw7WYSfailure

Ma colonne 'mot de passe' a ce type de données: VARCHAR(255) NOT NULL

Aucune erreur php n'apparaît donc la seule chose à laquelle je peux penser est que la valeur de hachage n'est pas formatée de la même manière lorsqu'elle sort de la base de données que lorsqu'elle est entrée, mais quand je fais écho aux valeurs, elles semblent être identique.

Sinon, comment puis-je déboguer ceci/quel est le problème avec mon code?

Merci

METTRE À JOUR:

Cela a certainement quelque chose à voir avec l'encodage:

$hardcode_hash = '$2y$10$JK1jumvvSIm/gP3fWE3k9O98MzvHKDRYCjRPBniYg9riACyQw7WYS';

echo $hash;
echo '<br/>';
echo $hardcode_hash;
echo '<br/>';

if( $hash == $hardcode_hash )
    echo 'success';
else echo 'failure';

//OUTPUT
$2y$10$JK1jumvvSIm/gP3fWE3k9O98MzvHKDRYCjRPBniYg9riACyQw7WYS
$2y$10$JK1jumvvSIm/gP3fWE3k9O98MzvHKDRYCjRPBniYg9riACyQw7WYS
failure

comment reformater la valeur SQL pour qu'elle corresponde à la sortie de password_hash? Voici ce que j'ai essayé:

(string)$hash
utf8_encode($hash)

si je fais:

$hash = settype($hash,"string");

if($hash == $hardcode_hash) renvoie vrai, mais password_verify($pass, $hash) renvoie toujours faux

14
Cbas

Trouvé le problème. quand j'ai fait ça:

echo strlen($hash)

il a imprimé 90, ce qui est étrange car il n'y avait certainement aucun espace à la fin lorsque j'ai imprimé le message de réussite/échec, et le champ a une longueur de varchar de 255

J'ai ajouté cette ligne:

$hash = substr( $hash, 0, 60 );

Et maintenant ça marche bien.

C'est étrange que personne d'autre ne semble avoir rencontré ce problème. Il existe des articles similaires sur password_verify, mais aucun d'entre eux n'a nécessité ce type de conversion, ni aucune conversion d'ailleurs:

php password_verify ne fonctionne pas

password_verify php not match

http://forums.phpfreaks.com/topic/283407-need-help-with-password-verify/

tilisation de PHP 5.5 fonction password_hash et password_verify

Une chose qui me dérange est que cela empêche le code d'être compatible avant. Comment savoir que le hachage comporte 60 caractères lorsque la valeur par défaut change?

12
Cbas

J'avais le même problème avec password_verify (). Pour moi, j'avais déclaré mon nom d'utilisateur et mot de passe VARCHAR (50). Par conséquent, il n'insérait pas la valeur de hachage dans ma base de données qui est évidemment plus de 50 caractères. Par conséquent, chaque fois que j'utilisais password_verify (), j'obtenais un faux. J'ai changé mes valeurs de base de données en varchar (255). Données insérées à nouveau, testées et cela fonctionne.

4
MosesK

Juste pour référence future. J'ai eu le même problème avec les mots de passe qui échouaient sans raison. Quand je l'ai regardé de plus près, j'ai vu que le champ de mot de passe dans la base de données n'était pas assez grand pour stocker le hachage complet, donc certains caractères ont été coupés. Après avoir augmenté la taille du champ de la base de données, cela a parfaitement fonctionné.

3
Kobus

J'ai eu le même problème que vous aviez avec cela ne fonctionnait pas, pour une raison quelconque, cela semble aider à mettre le:

$hash = substr( $hash, 0, 60 );

dans le code bien que ma chaîne contienne déjà 60 caractères.

2
Lexix

J'ai eu le même problème et cela ne fonctionnait toujours pas malgré le fait que mes colonnes de base de données étaient varchar (255), que les hachages étaient de 60 caractères et que mon encodage était UTF-8 tout au long. Je suis assez nouveau pour PHP et SQL donc je ne prétendrai pas comprendre exactement pourquoi cela a fonctionné, mais j'ai réussi à le réparer alors j'espère que ce message aidera d'autres personnes avec le même problème .

Il s'est avéré que la raison sous-jacente de password_verify () ne vérifiait pas mes hachages était parce que j'avais fait une instruction préparée qui utilisait une procédure stockée plus tôt dans le script sans récupérer correctement tous les résultats de la requête pour vider le tampon, avant de fermer et la réouverture de la connexion pour effectuer la requête suivante. L'appel de next_result () sur le mysqli_link après la fermeture de l'instruction garantira que tous les résultats seront consommés.
De plus, j'utilisais ensuite une autre instruction préparée avec une procédure stockée pour effectuer l'insertion du mot de passe, mais j'avais encore besoin d'appeler store_result () et free_result () même si aucun jeu de résultats n'était retourné par le insérer. Je suppose que la combinaison de ces éléments a corrompu mes données quelque part le long de la ligne, ce qui a pour résultat password_verify () renvoyant false sur des hachages apparemment identiques.

Cette réponse était pour un problème différent mais je l'ai trouvé utile pour apprendre à fermer correctement les instructions préparées avec des procédures stockées.

1
DBC