【问题标题】:PHP Can't use a hashed password in a PDO queryPHP 不能在 PDO 查询中使用散列密码
【发布时间】:2016-01-13 18:54:42
【问题描述】:

我目前是一名三年级网络开发学生,对于一个学校项目,我们必须使用 PDO 和哈希建立一个具有更改密码功能的网站,但是我遇到了一个我自己无法解决的问题,我在 google 和 stackoverflow 上也没有发现任何类似的问题。

我们必须在数据库中存储2个密码,旧密码(这是用户最后使用的密码);以及他们当前的密码(将用于登录。)

所有密码都使用标准 PHP 哈希存储(password_hash() 方法)

更改用户密码时,我必须从数据库中获取当前密码(用于登录的密码),并将其移动到 oldpassword(最后使用的密码)列,同时将新的散列密码放入数据库。

问题是: 我似乎无法在 PDO 查询中使用散列密码,我确实需要指出我以前从未使用过 PDO,但在谷歌搜索了一下之后,我不要认为我的查询有错误,而是传递给该查询的数据有错误。

这是我从数据库中获取所有当前数据的地方

/*prepare and execute a query*/
$sqlStatement = $this->db->prepare("SELECT username, password, oldpassword FROM users WHERE username = :username");
$sqlStatement->bindParam(":username", $username, PDO::PARAM_STR);
$sqlStatement->execute();

/*Fetch the query results*/
$values = $sqlStatement->fetch(PDO::FETCH_ASSOC);

这是我尝试使用 PDO SQL 查询将数据存储到数据库中的地方

/*Create variables to use in querys*/
$queryPassword = password_hash($password, PASSWORD_DEFAULT);

/*Update the passwords*/
$sqlStatement2 = $this->db->prepare("UPDATE password, oldPassword VALUES (:password, :oldpassword)");
$sqlStatement2->bindParam(":password", $queryPassword, PDO::PARAM_STR);
$sqlStatement2->bindParam(":oldpassword", $values["password"] , PDO::PARAM_STR);
$sqlStatement2->execute();

$password 和 $username 是从表单传递给函数以更改用户密码的变量。

public function updateUserPasswords($username, $password){

我觉得奇怪的是:如果我对 $values["password"] 执行 var_dump,我会得到以下数据:
字符串(60)“$2y$10$BBCpJxgPa8K.iw9ZporxzuW2Lt478RPUV/JFvKRHKzJhIwGhd1tpa”

我的查询错误为我提供了以下数据:
$2y$10$

好像只有哈希被发送到查询。

==EDIT==

发送到浏览器的 SQL 错误是:

Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VALUES ('$2y$10$AC.aMG/gNV9zwGB/v/g7keW9jsZ80kuejrSh693DPuhOYChFxA6wu', '$2y$10$' at line 1' in /srv/jip/www/www.jip.nl/classes/user.class.php:92 Stack trace: #0 /srv/jip/www/www.jip.nl/classes/user.class.php(92): PDOStatement->execute() #1 /srv/jip/www/www.jip.nl/pages/first_login.php(26): User->updateUserPasswords('username', 'password') #2 {main} thrown in /srv/jip/www/www.jip.nl/classes/user.class.php on line 92

【问题讨论】:

  • 您正在更新表中的所有密码
  • 数据库中密码字段的最大长度是多少?我猜是7
  • @noobie-php 为什么要使用 MySQL 散列函数? PHP 具有比 MySQL 更安全的哈希函数(例如 password_hash() 使用多轮 bcrypt)。
  • 用户在表单中输入密码 > 表单已发送 > PHP 哈希从表单输入 > PHP 将哈希存储在数据库中。这里一切都很好。
  • 你说的“查询错误”是什么?

标签: php mysql pdo hash passwords


【解决方案1】:

不要使用散列密码检索数据,因为password_hash() 会在使用时生成具有不同盐的新散列

仅使用用户名检索记录,然后使用password_verify() 验证密码

编辑

您的更新查询引用了列,但没有表,并且没有 WHERE 子句:

$sqlStatement2 = $this->db->prepare("UPDATE users SET password=:password, oldPassword=:oldpassword WHERE username = :username");
$sqlStatement2->bindParam(":password", $queryPassword, PDO::PARAM_STR);
$sqlStatement2->bindParam(":oldpassword", $values["password"] , PDO::PARAM_STR);
$sqlStatement2->bindParam(":username", $username, PDO::PARAM_STR);
$sqlStatement2->execute();

使用适当的值绑定

【讨论】:

  • 好的,感谢您的快速回复,我会试一试,等我完成后再回来查看。
  • 解释得很好,很合乎逻辑
  • where 子句确实没有了,还没有添加,因为该表目前只有一个测试结果.. 至于表,它包含在 $this ->分贝
【解决方案2】:

原来我的查询确实不正确,自从我上次进行更新查询以来已经有一段时间了,我把它放在与插入查询相同的格式。

Mark Ba​​ker 的解决方案还解决了从数据库中检索旧密码的问题。仅使用用户名检索信息是有效的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-13
    • 2012-05-30
    • 1970-01-01
    • 2019-02-15
    • 1970-01-01
    • 2011-04-06
    • 2018-02-24
    相关资源
    最近更新 更多