2009-01-28 56 views
5

¿Cómo se verifica si un usuario ha ingresado la contraseña correcta para iniciar sesión?PHP & MySQL compare contraseña

Esto es lo que (de un montón de combinaciones ...) que estoy haciendo:

<? 

$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."; 

?> 

Como puedo ver desde que la salida, hay algo mal en el bit mysql_result, pero no puedo averiguar el camino correcto.

¿Puede alguien ayudarme por favor.

+3

Nosotros aquí en stackoverflow no responder a preguntas sobre los inicios de sesión. Preferimos explicar, con gran detalle técnico, cómo desinfectar las aportaciones de los usuarios. Es mejor estar seguro que tener un sitio web funcional. – Grant

+5

@Grant: Estás bromeando, ¿verdad? –

+0

Tenga en cuenta que las respuestas en esta página no están actualizadas y, por lo tanto, no son seguras, consulte esta [pregunta] (http://stackoverflow.com/q/4795385/575765). – martinstoeckli

Respuesta

17

Veo que está almacenando un hash de la contraseña en la base de datos, pero para el beneficio de otros lectores, nunca almacene contraseñas en texto sin formato en la base de datos. ¡No quieres ser like Monster.com.uk!

Debería utilizar una función hash más fuerte que MD5(). Lo ideal es que uses SHA256. Este método hash está disponible en PHP utilizando la función hash().

También debe aplicar un salt aleatorio a la contraseña. Almacene un valor de sal diferente para la cuenta de cada usuario. Esto ayuda a vencer los ataques de diccionario y los ataques rainbow table.

Debería aprender a utilizar la extensión mysqli en lugar de la antigua extensión mysql. Mysqli admite consultas parametrizadas, por lo que puede reducir la vulnerabilidad a algunos ataques de inyección SQL.

Aquí hay algunos ejemplos de código. Yo no lo he probado, pero debe ser bastante cerca de trabajo:

$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; 

Algunas otras personas sugieren la consulta debe probar la login = ? AND password = ? pero no me gusta hacer eso. Si hace esto, no puede saber si la búsqueda falló porque el inicio de sesión no existía o porque el usuario proporcionó una contraseña incorrecta.

Por supuesto, no debe revelar al usuario lo que causó el intento fallido de inicio de sesión, pero usted puede necesitar saber, por lo que puede registrar actividad sospechosa.


@Javier dice en su respuesta que no se debe recuperar la contraseña (o hash de la contraseña en este caso) de la base de datos. No estoy de acuerdo

Javier muestra llamando al md5() en código PHP y enviando la cadena hash resultante a la base de datos. Pero esto no permite salarizar la contraseña fácilmente. Tienes que hacer una consulta por separado para recuperar la sal de este usuario antes de poder hacer el hash en PHP.

La alternativa es enviar la contraseña de texto claro a través de la red desde su aplicación PHP a su servidor de base de datos. Cualquier persona que intercepte su red puede ver esta contraseña. Si tiene consultas SQL registradas, cualquier persona que obtenga acceso a los registros puede ver la contraseña. Los piratas informáticos motivados incluso pueden sumergirse en el basurero para encontrar medios antiguos de copia de seguridad del sistema de archivos, ¡y pueden leer los archivos de registro de esa manera!

El riesgo menor es obtener la cadena de hash de la contraseña de la base de datos en la aplicación PHP, compararla con el hash de la entrada del usuario (también en código PHP), y luego descartar estas variables.

+0

Faltaba una sola cosa en su código. mysqli_prepare() toma dos parámetros, el primero es el resultado de la instrucción mysqli_connect(). Como estaba usando mysql_connect(), no funcionaba. Pero después de la modificación, funciona bien. Gracias por tu ayuda. – Mussnoon

+0

Gracias por la captura, lo he arreglado. Sin embargo, no me mostré conectando a la base de datos. Solo asumí que tienes un objeto $ mysqli en vivo. –

+0

mysqli es demasiado horrible para usar (tristemente) – cletus

1

algunos puntos:

  • no inserte datos de cadena en la cadena de consulta. Especialmente datos proporcionados por el usuario. ¿Qué pasaría si inicio sesión con "Robert", drop table customer "?. Utilice las rutinas de escape o (mucho mejor) use declaraciones preparadas y parámetros de vinculación.
  • NO almacene contraseñas de texto simple en su base de datos. (está bien en esto)
  • NO recupere las contraseñas de su base de datos.

lo que suelo hacer es algo como:

$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

Lo llamamos pequeños Bobby Tables. – Powerlord

+3

Probablemente deberías señalar que no estás usando código PHP nativo aquí. bindvalue() me confundió un poco, y aún más después de no encontrarlo en php.net. Finalmente encontré PHP Data Objects (PDO) en línea que cubría la información en su ejemplo. – Sampson

2

En primer lugar, asegúrese de escapar adecuadamente las variables antes de utilizarlas en la consulta - uso mysql_real_escape_string().

Entonces, ¿por qué no utilizar la función MySQL MD5 para verificar un inicio de sesión válido en su consulta?

SELECT login FROM customer WHERE login='$login' AND password = MD5('$password') 

Entonces simplemente use mysql_num_rows() para contar el número de filas devueltas.

0

Obtener la contraseña del usuario método POST FORM y convertir $ _POST [ 'password'] // del formulario // en formato apropiado en php/jsp/cualquier otro luego comparar con la contraseña con formato en su base de datos

general Se usa cifrado md5 cuando se puede comparar md45 ('{$ _ POST [' password ']}') = presente en su db; o generalmente mysql usa la contraseña ('tu contraseña') mientras creas la contraseña, primero concierta tu $ _POST ['contraseña'] en mysqli_query y mysqli_fetch_array para obtener el valor de la contraseña cifrada y luego compara.

0

Mayor que PHP 5.6, puede usar la función 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 realidad, esta función no debe usarse para comparar hashes de contraseñas (los hashes comparables no son adecuados para las contraseñas), en su lugar use [password_verify()] (http://www.php.net/manual/en/function.password-verify. php) y genera el hash con [password_hash()] (http://www.php.net/manual/en/function.password-hash.php). – martinstoeckli