我已经构建了一个非常简单的登录/注册脚本,它使用密码哈希函数,如下所示:
$password = password_hash($password, PASSWORD_DEFAULT);
所有这一切都需要我的密码并以我期望的格式将其弹出到我的数据库中。我遇到了登录部分和使用password_verify()
函数的问题,我的登录脚本现在非常简单,并且很容易注入SQL,但我只是想了解它是如何工作的。
这是我的登录脚本:
<?php
ini_set('display_errors',1);
error_reporting(E_ALL);
ob_start();
include('db_con.php');
$username=$_POST['username'];
$password=$_POST['password'];
$username = stripslashes($username);
$password = stripslashes($password);
$sql="SELECT * FROM users WHERE username='$username' and password='$password'";
$result=mysqli_query($db,$sql);
$count=mysqli_num_rows($result);
if($count==1){
session_start();
$_SESSION['loggedin'] = true;
$_SESSION['username'] = $username;
header("location:home.php");
}
else {
echo "Wrong Username or Password";
}
ob_end_flush();
?>
我不知道我需要使用password_verify()
,因为我知道它需要2个参数,一个是密码而另一个是哈希?
答案 0 :(得分:9)
基本上password_hash
会创建一个名为 salt 的哈希值。这个哈希值对于这个哈希是唯一的,并且是哈希的前几个字符,并且再次运行password_hash将为您提供随机生成的不同盐。
在散列过程中将salt添加到密码中以避免攻击,例如只查看结果的哈希数据库。以下面的例子为例:
$2a$10$4m/TjukW7De5OszVFYL9quIXNz5pSDc2P.jX5A138G493Vqr0vUiO
$2a
是标识符,表示哈希是bcrypt
$10$
告诉我们用10轮bcrypt哈希
4m/TjukW7De5OszVFYL9qu
是盐
IXNz5pSDc2P.jX5A138G493Vqr0vUiO
这是散列值。
因此,如果你只是使用password_hash
生成哈希,它会生成一个不同的随机盐,因此哈希将会有所不同。 password_verify
函数抓取您已经创建的哈希值,从中获取盐并使用您拥有的盐来哈希值。
password_verify($value, $hash)
用作$value
将是用户输入的密码,并且盐需要$hash
以及旧哈希的轮数。
答案 1 :(得分:2)
我看到您使用了mysqli_*
个函数。但是如果你不使用准备好的陈述,无论如何都不会帮助你。以下是mysqli_*
函数与预处理语句以及问题解决方案的更好用法 -
首先通过用户名从DB获取哈希密码。
$username=$_POST['username'];
$password=$_POST['password'];
//NO NEED of stripslashes if using prepared statements.
$sql="SELECT password FROM users WHERE username = ?";
$stmt = mysqli_prepare($link, $sql);
/* bind parameters for markers */
$stmt->bind_param("s", $username);
/* execute query */
$stmt->execute();
/* store result (So that you can check num_rows immediately.) */
$stmt->store_result();
如果未找到任何行,则表示您已经抛出“无效用户”错误!否则,只需使用password_verify()
以这种方式验证密码 -
if($stmt->num_rows()) {
/* bind result variables */
$stmt->bind_result($hashed_password);
/* fetch value */
$stmt->fetch();
if(password_verify($password, $hashed_password)) {
//Login
} else {
//Password mismatch
}
} else {
//User not found.
}
/* free result */
$stmt->free_result();
/* close statement */
$stmt->close();
如果您正确使用预准备语句,则不再需要使用
stripslashes()
。只需删除这两行:
$username = stripslashes($username); //REMOVE THIS LINE
$password = stripslashes($password); //REMOVE THIS LINE
答案 2 :(得分:-3)
password_hash和password_verify在撰写本文时使用bcrypt。每次散列密码时,bcrypt都不会给你回相同的字符串。
使用数据库中的哈希的步骤: