【问题标题】:Need help using password_verify with prepared statements, password not verifying properly需要帮助将 password_verify 与准备好的语句一起使用,密码未正确验证
【发布时间】:2020-08-25 14:04:49
【问题描述】:

我讨厌成为新人问你能不能修复这个代码,或者至少告诉我怎么做,但我要在这里一个月,试图找出它为什么不起作用,如果它不明显,我'从二月份才开始编码,所以我的知识非常有限,我一直在学习几门不同的课程,并且已经成功地使用 md5 和许多其他不太安全的方式编写了类似的脚本,但我不想放置一个网站在线使用这些脚本。

我的问题是我可以注册用户密码、用户名等,并在数据库中正确存储和散列,但是当我尝试以该用户身份登录时,我无法弄清楚为什么我没有正确验证密码,我总是被定向到 pwd 错误行。

我在一周中的大部分时间都在工作,除了周末之外几乎没有时间修补这个问题,但现在是第四个周末,我真的很想解决这个问题,而不必重写整个事情。我真的很想使用准备好的语句来做这样的事情,我已经将每个语句与 php 手册进行了比较,它看起来对我来说是有效的,我一遍又一遍地检查它,试图找出问题所在,但我所做的一切检查似乎应该可以工作。我迷路了。

以下是某人查看正在发生的事情应该需要的文件。 . .

注册脚本

<?php 
  require "header.php";
?>

  <main>
   <div class="wrapper-main">
     <section class="section-default">
       <h1>Signup</h1>
        <form class="form-signup" action="includes/signup.inc.php" method="POST">
          <input type="text" name="mailuid" placeholder="Username">
          <input type="email" name="mail" placeholder="E-mail">          
          <input type="password" name="pwd" placeholder="Password">
          <input type="password" name="pwd-repeat" placeholder="Repeat Password">
          <button type="submit" name="signup-submit">Signup</button>
        </form>
     </section>
   </div>
  </main>

<?php
   require "footer.php";
?>
<?php
if (isset($_POST['signup-submit'])) {

 require  'dbh.inc.php';

 $username = $_POST['mailuid'];
 $email = $_POST['mail'];
 $password = $_POST['pwd'];
 $passwordRepeat = $_POST['pwd-repeat'];
  /// checks that user filled all feilds
 if (empty($username) || empty($email) || empty($password) || empty($passwordRepeat)) {
   header("Location: ../signup.php?error=emptyfeilds&uid=".$username."&mail=".$email);  //error msgs to user
   exit();
  }
else if (!filter_var($email, FILTER_VALIDATE_EMAIL) && !preg_match("/^[a-zA-Z0-9]*$/", $username)) {
  header("Location: ../signup.php?error=invalidmail&uid");
  exit();
}
else if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
 header("Location: ../signup.php?error=invalidmail&uid=".$username);
 exit();
}
else if (!preg_match("/^[a-zA-Z0-9]*$/",$username)) {
  header("Location: ..signup.php?error=imvalidui&mail=".$email);
  exit();
}
else if ($password !== $passwordRepeat) {
  header("Location: ../signup.php?error=passwordcheck&id=".$username."&mail=".$email);
  exit();
}
else {
  // checks for matching users in db
  $sql = "SELECT * FROM users WHERE uidUsers=?";
    $stmt = mysqli_stmt_init($conn);
    if (!mysqli_stmt_prepare($stmt, $sql)) {
      header("Location: ../signup.php?error=sqlerror");
      exit();
    }
    else {
      mysqli_stmt_bind_param($stmt, "s", $username);
      mysqli_stmt_execute($stmt);
      mysqli_stmt_store_result($stmt);
      $resultcheck = mysqli_stmt_num_rows($stmt);
      if ($resultcheck > 0) {
        header("Location: ../signup.php?error=usertaken=".$username);
        exit();
      }
      else {

        $sql = "INSERT INTO users (uidUsers, emailUsers, pwdUsers) VALUES (?, ?, ?)";
        $stmt = mysqli_stmt_init($conn);
        if (!mysqli_stmt_prepare($stmt,$sql)) {
          header("Location: ../signup.php?error=sqlerror");
          exit();
       }
       else {
         $hashedPwd = password_hash($password, PASSWORD_DEFAULT);

         mysqli_stmt_bind_param($stmt, "sss", $username,$email,$hashedPwd);
         mysqli_stmt_execute($stmt);
         header("Location: ../index.php?signup=success");
         exit();
       }

      }
    }

    }
    mysqli_stmt_close($stmt);
    mysqli_close($conn);

 }
 else {
   header("Location: ../signup.php");
   exit();
 }

现在是登录脚本

<?php

if (isset($_POST['login-submit'])) {

  require 'dbh.inc.php';

  $mailuid = $_POST['mailuid'];
  $password = $_POST['pwd'];

  if (empty($mailuid) || empty($password)) {
    header("Location: ../index.php?error=emptyfields");
    exit();
  }
  else {
    $sql = "SELECT * FROM users WHERE uidUsers=?;";
    $stmt = mysqli_stmt_init($conn);
    if (!mysqli_stmt_prepare($stmt, $sql)) {
     header("Location: ../index.php?error=sqlerror");
     exit();
    }
    else {

      mysqli_stmt_bind_param($stmt, "s", $mailuid);
      mysqli_stmt_execute($stmt);
      $result = mysqli_stmt_get_result($stmt);
      if ($row = mysqli_fetch_assoc($result)) {
        $pwdcheck = password_verify($password, $row['pwdUsers']);
        if ($pwdCheck == false) {
          header("Location: ../index.php?error=wrongpwd");
          exit();
        }
        else if ($pwdCheck == true) {
          session_start();
          $_SESSION['userId'] = $row['idUsers'];
          $_SESSION['userUid'] = $row['uidUsers'];

          header("Location: ../index.php?login=success");
          exit();
        }
        else {
          header("Location: ../index.php?error=wrongpwd");
          exit();
        }    
      }
      else {
         header("location: ../index.php?error=nouser");
         exit();
      }

    }
  }

}
 else {
   header("Location: ../index.php");
 exit();
}

【问题讨论】:

  • 可变案例问题? ...您将password_verify 设置为$pwdcheck,然后与$pwdCheck 进行比较?如果是拼写错误,那么这个问题可能会被删除。然后你可以重构代码的那个区域来做一个简单的 if/else 检查,而不需要 else if。
  • 您在 ?error= 中收到什么错误
  • 一般提示:欢迎来到 SO,它是一个帮助网站,因此您无需讲述您寻求帮助的原因。额外的恼怒词不会使您的问题易于阅读并分散问题的注意力。尽管如此,您还是提供了很多细节,非常感谢。 “密码错误行”。可以更严格地指定。欢迎来到 SO。我们期待您的更多问题。
  • 其他代码/sql提示:如果您有if { .. exit(); },请不要创建else 子句,它只会使缩进和跟踪变得困难。在进行 SQL 选择时,仅获取您需要的行并避免使用“*”,这可以使其在 SQL 服务器端更加高效。与其在插入前检查一行,不如使用唯一/主键来确保数据是唯一的。捕获重复的键异常以确保它不重复 - 这不受竞争条件的影响。
  • 忘记添加:...如果您知道服务器 error_log 的位置,则应该有关于 undefined variable $pwdCheck 的 PHP 通知已记录。在开发过程中保持该日志可用,以帮助捕获此类问题或其他问题,例如 PHP 致命错误。我通常会在单独的终端中打开tail -F /path/to/error_log,以便随时检查。

标签: php sql prepared-statement password-hash


【解决方案1】:

您将用户名放在uidUsers 中,将电子邮件放在emailUsers 字段中,然后使用"SELECT * FROM users WHERE uidUsers=?;" 读取它并将其绑定到$mailuid

我认为应该改为"SELECT * FROM users WHERE emailUsers=?;"

还要确保保存密码哈希的数据库字段的类型为varchar(255),较短的字段可能会截断密码哈希。

【讨论】:

    【解决方案2】:

    感谢 Paul T。你说得对,关于错误日志的提示很有帮助,我没有意识到这一点。正如我所说,我不久前才刚刚开始学习这一切。可悲的是,我在教程中被教导以这种方式编写 password_verify 语句。我将有问题的部分更改为 . . .

      <?php
    
    if (isset($_POST['login-submit'])) {
    
      require 'dbh.inc.php';
    
      $mailuid = $_POST['mailuid'];
      $password = $_POST['pwd'];
    
      if (empty($mailuid) || empty($password)) {
        header("Location: ../index.php?error=emptyfields");
        exit();
      }
      else {
        $sql = "SELECT * FROM users WHERE uidUsers=?";
        $stmt = mysqli_stmt_init($conn);
        if (!mysqli_stmt_prepare($stmt, $sql)) {
         header("Location: ../index.php?error=sqlerror");
         exit();
        }
        else {
    
          mysqli_stmt_bind_param($stmt, "s", $mailuid);
          mysqli_stmt_execute($stmt);
          $result = mysqli_stmt_get_result($stmt);
          if ($row = mysqli_fetch_assoc($result)) {
           if (password_verify($password, $row['pwdUsers'])) {
             session_start();
             $_SESSION['userId'] = $row['idUsers'];
             $_SESSION['userUid'] = $row['uidUsers'];
    
             header("Location: ../index.php?login=success");
             exit();
            }
    
            else {
              header("Location: ../index.php?error=wrongpwd");
              exit();
            }
    
          }
          else {
             header("location: ../index.php?error=nouser");
             exit();
          }
    
        }
      }
    
    }
     else {
       header("Location: ../index.php");
     exit();
    }
    

    现在这一切终于按预期工作了。是否存在任何未解决的安全问题?

    【讨论】:

    猜你喜欢
    • 2018-10-21
    • 1970-01-01
    • 2015-12-08
    • 2018-09-30
    • 2021-10-11
    • 2016-12-17
    • 1970-01-01
    • 2018-09-26
    • 1970-01-01
    相关资源
    最近更新 更多