Php 登记册及;登录密码哈希方法相同,但不起作用

Php 登记册及;登录密码哈希方法相同,但不起作用,php,mysql,login,hash,pdo,Php,Mysql,Login,Hash,Pdo,我在这里看到了类似的问题,但我认为答案不适用于我,如果答案适用,我很抱歉 以下是包含两个过程的代码片段: 注意:登录和注册在没有散列元素的情况下运行良好 if(设置($\u POST['username'])&($\u POST['password'])){ $username=trim($_POST['username']); $username=strtolower($username); $password=trim($_POST['password']); $salt=hash('md5

我在这里看到了类似的问题,但我认为答案不适用于我,如果答案适用,我很抱歉

以下是包含两个过程的代码片段:

注意:登录和注册在没有散列元素的情况下运行良好

if(设置($\u POST['username'])&($\u POST['password'])){
$username=trim($_POST['username']);
$username=strtolower($username);
$password=trim($_POST['password']);
$salt=hash('md5',“$username”);
$password=hash('sha256',“$password”。$salt”);
$stmt=$dbh->prepare(“从'1_users'中选择'id',其中用户名=?密码=?限制1”);
$stmt->bindValue(1,$username,PDO::PARAM_STR);
$stmt->bindValue(2,$password,PDO::PARAM_STR);
$stmt->execute();
如果($stmt->rowCount()){
//匹配
$results=$stmt->fetch(PDO::fetch_ASSOC);
$\会话['id']=$results['id'];
$\u会话['logged\u in']=true;
$_会话['ip']=hash('sha1',“{$_服务器['REMOTE_ADDR']}”);
标题(“位置:account.php”);
}
否则{
$error='无效的用户名/密码!';
}
}
如果(isset($_POST['register'])){
//检查所有字段。。
如果((空($_POST['r_username']))|(空($_POST['r_password']))|(空($_POST['re_password']))|(空($_POST['email'])){
$r_error='其中一个字段为空';
}
$stmt=$dbh->prepare(“从`1_成员`WHERE`username`=?LIMIT 1`中选择`username`”);
$username=strtolower($_POST['r_username']);
$username=trim($username);
$stmt->bindValue(1,$username,PDO::PARAM_STR);
$stmt->execute();
$row=$stmt->rowCount();
如果($行){
$r_error='该用户名已在使用';
}
else if($_POST['r\u password'])!=($_POST['r\u password'])){
$r_error='密码不匹配';
}
else if(strlen($_POST['r_username'])bindValue(1,$username,PDO::PARAM_STR);
$stmt->bindValue(2,$password,PDO::PARAM_STR);
$stmt->bindValue(3$email,PDO::PARAM_STR);
$stmt->execute();
$\会话['id']=$dbh->lastInsertId();
$\u会话['logged\u in']=true;
$_会话['ip']=hash('sha1',“{$_服务器['REMOTE_ADDR']}”);
如果($\会话['active\ u cart']){
标题(“位置:cart.php”);
}
否则{
标题(“位置:account.php”);
}
}
}
在将哈希添加到密码之前,它的功能正常,我不确定我的问题是什么

调试:

用户名:admin1
密码:admin1


登录过程将密码转换为:
927364bb72cee168bd52c45a5d131b5923e2926eb6e8f046d6d7e5765cc3401

注册过程将密码创建为:
927364bb72cee168bd52c45a5d131b5923e2926eb6e8f0f46d6d7e5765cc3401

他们匹配,那么出了什么问题

此外,如果我在这里有错误的想法,或者如果我忽略了重要的安全步骤,请你建议更好的方法

另外,我不太担心电子邮件验证,我完全知道有很多预先制作的snipplet可用于验证电子邮件,我将在晚些时候进行讨论

任何抄送都是非常受欢迎的


编辑:脚本返回“无效用户名/密码组合”。

我怀疑哈希密码的数据库字段太小,该字段必须能够存储64个字符

即使您可以解决这个问题,您也有一个不安全的密码存储方案(SHA256对于哈希密码来说太快了)。看看PHP函数,它将生成一个BCrypt哈希,并负责生成一个安全的salt。salt将是生成的62个字符字符串的一部分,因此不需要单独存储salt。对于较旧的PHP版本,也存在一个安全的salt

// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);

// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);

这也意味着您不能直接在SQL语句中验证密码,而是从数据库中读取哈希(通过用户名),然后使用此哈希调用password_verify()。

可能是,PDOStatement::rowCount()在对SELECT查询执行时不会返回“1”。请看这里:


(特别是示例#2)

您不使用的具体原因是什么?@SecondRikudo我不知道,是什么让它比hash更特殊?它使用bcrypt并且更安全。它还非常容易使用(它为您生成盐,并具有另一个函数
password\u verify()
来轻松地验证密码)因此,如果我删除hash和salt方法,并替换为注册的
$password=password\u hash('$password');
,以及登录的
$password=password\u verify('$password');
,它会工作吗?或者我有错误的想法吗?不确定这是否会解决您的问题(尽管可能,请注意,您需要PHP5.5或更高版本)。但是,它将使您的代码更简单,更易于阅读和调试。
// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);

// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);