password_verify不工作的PHP

时间:2017-09-18 15:18:39

标签: php mysql pdo

我似乎无法解决为什么password_verify不起作用。上传的密码都是哈希值。使用PDO进行密码验证没有返回任何内容,我已将密码上传页面添加到底部,因为这里可能存在问题?根据我的理解,当我在错误日志中运行时,$ hash目前没有任何价值。如果密码验证工作不正常或我的代码中有错误,我不是用户。我很感谢你的帮助。

  if (isset($_POST['submit'])) {
      $username = $_POST['username'];
      $password = $_POST['password'];
      $q = $handler->prepare('SELECT * FROM users WHERE username = ?');
      $q->execute(array($username));
      $result = $q -> fetch(PDO::FETCH_ASSOC);
      if ($result !== FALSE) {
          $hash_pwd = $result['password'];
          $hash = password_verify($hash_pwd, $password);
          error_log($password);
          error_log($username);
          error_log($hash_pwd);
          //error_log($hash);
          //error_log((int) $hash);
          if ($hash) {
              $username = $_SESSION['username'];
              error_log("loggedin");
              header("location:index.php");return;
          }
          else {
              echo '<p class="error-message3"><br><br>You have ented an incorrect login!<br>Please try again</p>';
          } 
      }
  }
  ?>

    if
  (isset($_POST['username']) && isset($_POST['password']))
       {
        if (empty($_POST['username']) || empty($_POST['password'])) {
              echo('<p class="error-message2">'.'Please Fill All Boxes'.'</p>');
          } 
        else {  
              $username = $_POST['username'];
              $password = password_hash($pass, PASSWORD_DEFAULT);
              $sql = "INSERT INTO users (username, password) VALUES (:username, :password)";
              $query = $handler->prepare($sql);
              $query->execute(array(
                ':username' => $username,
                ':password' => $password,
                 ));
              echo('<p class="error-message2">'.'Thank You For Your Submission!'.'</p>');
          }
}
?>

2 个答案:

答案 0 :(得分:1)

根据原始问题中的代码和评论中的代码,您似乎正确使用了password_hash()password_verify(),并且无法检测到代码整体结构的另一个明显错误,所以我怀疑数据本身有些奇怪。

例如,您的SELECT可能会返回多行(如果您未在username列上设置唯一索引,则可能有两个用户具有相同的{ {1}},但不同的username - 您没有向我们展示表结构/索引。)

为了进一步调试,我建议改变你的代码:

password

请告诉我们if (isset($_POST['submit'])) { $username = $_POST['username']; $password = $_POST['password']; $q = $handler->prepare('SELECT * FROM users WHERE username = ?'); $q->execute(array($username)); if ($q->rowCount() > 0){ error_log((string) ($q->rowCount())); $result = $q -> fetch(PDO::FETCH_ASSOC); $hash_pwd = $result['password']; $hash = password_verify($password, $hash_pwd); error_log($hash_pwd); error_log($hash); error_log((int) $hash); if ($hash == 0) { error_log("hashwrong"); echo '<p class="error-message3">'.'<br>'.'<br>'."You have ented an incorrect login! <br>Please try again.".'</p>'; } else { $_SESSION['username'] = $username; error_log("loggedin"); header("location: index.php");return; } } } 语句转出的内容。为了使其可读,您可以编辑您的问题并在结尾追加结果(而不是将其放入评论中)。但是请不要改变已经被评论或答案引用的问题的那些部分(否则,后来的读者将无法从中获得任何意义)。

编辑1

我注意到代码中可能存在错误。我没有立即看到它的原因是我从未使用过PHP。

但是,您应该使用error_log()来检查::rowCount()语句是否返回任何行。来自::rowcount reference in the PDO manual

  

PDOStatement :: rowCount()返回受影响的行数   最后由相应的DELETE,INSERT或UPDATE语句执行   PDOStatement对象。

     

如果关联的PDOStatement执行的最后一条SQL语句是   一个SELECT语句,一些数据库可能会返回行数   由该声明返回。但是,不保证这种行为   适用于所有数据库,不应依赖于便携式数据库   应用

另一方面,从PDO手册中的::fetch reference

  

此函数的成功返回值取决于获取   类型。在所有情况下,失败时都会返回FALSE。

那么请你删除现有的行

SELECT

并替换

$result = $q -> fetch(PDO::FETCH_ASSOC);

通过

if ($q->rowCount() > 0) {

并告诉我们结果?

如果这不记录任何错误消息(PHP警告除外),那么我们知道$result = $q -> fetch(PDO::FETCH_ASSOC); if ($result !== FALSE) { 由于某种原因没有返回任何行。请记住,根据上面显示的手册部分,SELECT可能没有返回行,但SELECT仍然大于0。

如果仍然记录错误消息,我们将不得不进行额外的调试。

编辑2

我们现在知道您的$q->rowCount()会返回一行,并且获取数据没有问题。现在我自己用完了选项。

恕我直言,只剩下一个解释:SELECT确实是错误的(从代码的角度来看)。如果POST请求的编码错误,最终可能会发生这种情况。要做出决定,我们可以执行以下步骤:

1)出于测试目的,将新用户插入$password表。此用户的usersusername应仅包含ASCII范围内的字符。例如,选择password作为用户名(在'AAAAA...'唯一后添加'A'个字符),将username添加为'B'

然后使用password / username再次运行您的脚本,并告诉我们发生了什么。

此测试的意义在于防止因不适当的字符串/ POST数据编码/解码而可能出现的问题。

2)在代码中再插入两行:

password

将这些行放在其他error_log($username); error_log($password); 调用所在的相同位置,并检查这是否确实输出了您所期望的内容,即确切地和字面上输出到脚本的值(即您拥有的值)在提交之前输入您的表格。)

让我们知道这两行输出的内容。

3)如果1.中描述的测试有效:

确保调用脚本的HTML页面已明确设置正确的编码。例如,有类似

的内容
error_log()
HTML标题中的

(请注意,这适用于XHTML; HTML 5或HTML 4.x的语法或标题可能不同;您必须对其进行研究。)

请告诉我们当时会发生什么。

4)如果1.中描述的测试有效:

我不知道您实际上是如何调用该脚本的,但无论如何,在调用脚本时还要另外设置正确的编码。例如,如果您通过AJAX调用脚本,请执行类似

的操作
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />;

如果你直接打电话&#34;直接&#34;从表单中,然后执行类似

的操作
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");

请告诉我们当时会发生什么。

5)如果1.中描述的测试有效:

确保您的网络服务器不会覆盖HTML网页中设置的编码。配置服务器的方式取决于服务器软件。对于Apache,禁用所有<form method="post" enctype="..." accept-charset="UTF-8"> 指令(通过注释掉它们)。

请告诉我们当时会发生什么。

编辑3

错误在上传代码中。您在AddDefaultCharset中使用$pass,但hash_password()未在任何地方初始化。所以只需添加

$pass

在现有的行

之后
$pass=$_POST['password'];

然后创建一个新的$username=...; / username组合并尝试使用您当前的登录代码登录(但请记住再次检查password的参数是否顺序正确)。它应该工作。

答案 1 :(得分:0)

手册:

boolean password_verify ( string $password , string $hash )
     

https://php.net/password_verify

您的代码:

$hash = password_verify($hash_pwd, $password);

您只是将两个参数反转为password_verify