PHP更改帐户密码制动以验证当前密码

时间:2017-06-29 10:58:32

标签: php sql-injection password-hash

我正在尝试为我的网站更改您的帐户密码功能。 登录代码工作正常,使用bcrypt对密码进行哈希处理,登录验证并确认帐户名和密码与输入的密码相符。

我正在尝试使用相同的算法来检查当前传递和数据库传递验证,但似乎缺少某些东西。 我经常从输入的密码和当前错误的密码错误中获得不同的哈希值。

这是我在php文件中使用的确切代码。

<?php
session_start();

function test_input($data) {
   $data = trim($data);
   $data = stripslashes($data);
   $data = htmlspecialchars($data);
   return $data;
}

$client_new_password_err = $client_current_password_err = $client_confirm_new_password_err = $general_err = "";

try {
    $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
    // set the PDO error mode to exception
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $user_check = $_SESSION['login_user'];
    $stmt = $conn->prepare("SELECT UserName FROM user_main WHERE UserName='$user_check'");
    $stmt->execute();
    foreach ($stmt->fetch(PDO::FETCH_ASSOC) as $arr) {
        $login_session = $login_session . $arr;
    }
    if (empty($login_session)) {
        $conn = null;
        header('Location: login.php');
    }
    $stmt = $conn->prepare("SELECT Email FROM user_main WHERE UserName='$user_check'");
    $stmt->execute();
    foreach ($stmt->fetch(PDO::FETCH_ASSOC) as $arr) {
        $login_email = $login_email . $arr;
    }
}
catch(PDOException $e)
{
    echo $stmt . "<br>" . $e->getMessage();
}
$conn = null;

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    if (!empty($_POST["current-password"])) {
        $client_current_password = test_input($_POST['current-password']);
        $cost = [
            'cost' => 11,
        ];
        $client_current_hashed_password = password_hash($client_current_password, PASSWORD_BCRYPT, $cost);
    } else {
        $client_current_password_err = "No input on Current Password";
    }
    if (!empty($_POST['new-password'])) {
        $client_new_password = test_input($_POST['new-password']);
        $cost = [
            'cost' => 11,
        ];
        $client_new_hashed_password = password_hash($client_new_password, PASSWORD_BCRYPT, $cost);
    } else {
        $client_new_password_err = "No input on New Password";
    }
    if (!empty($_POST['confirm-new-password'])) {
        $client_confirm_new_password = test_input($POST['confirm-new-password']);
        $cost = [
            'cost' => 11,
        ];
        $client_confirm_new_hashed_password = password_hash($client_confirm_new_password, PASSWORD_BCRYPT, $cost);
    } else {
        $client_confirm_new_password_err = "No input on New Password";
    }
    if ($client_new_hashed_password == $client_confirm_new_hashed_password) {
      $to_change_pass = 1;  // not yet implemented
    } else {
      $to_change_pass = 0;  // not yet implemented
    }
}

if (!empty($client_current_hashed_password) && !empty($client_new_hashed_password) && !empty($client_confirm_new_hashed_password)) {
    try {
        $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
        // set the PDO error mode to exception
        $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $user_check = $_SESSION['login_user'];
        $stmt = $conn->prepare("SELECT Password FROM user_main WHERE UserName='$user_check'");
        $stmt->execute();
        foreach ($stmt->fetch(PDO::FETCH_ASSOC) as $db_hash_pass) {
            if(password_verify($client_current_password, $db_hash_pass)) {
                $stmt = $conn->prepare("UPDATE user_main SET Password = '$client_new_hashed_password' WHERE UserName = '$user_check'");
            } else {
                  $general_err = "Entered current password does not match the actual password for this account. Please try again.";
              }
        }
    }
    catch(PDOException $e)
    {
        echo $stmt . "<br>" . $e->getMessage();
    }
    $conn = null;
}
?>

主要问题是我应该如何检查输入的当前通行证是否与数据库中的通行证匹配? 我应该使用客户输入的散列版本,还是使用纯文本密码?

这是100%可操作的登录密码验证码

if (!empty($_POST['password'])) {
    if (!preg_match("/^[a-zA-Z0-9 ]*$/",$_POST['password'])) {
         $usernameErr = 'Only Letters and Numbers';
    } else {
    $client_password = test_input($_POST['password']);
      if(password_verify($client_password, $hashed_password)) {
        $_SESSION['login_user'] = $client_username;
        header("location: profile.php");

其中$ hashed_pa​​ssword是从数据库列密码中提取的,用户名匹配,这里有效。

正如您所看到的,我对字母和数字的密码有限 - 奖金问题:通过允许在密码中使用所有字符,是否会产生任何类型的注入威胁?

1 个答案:

答案 0 :(得分:0)

不要哈希,而是验证。 - jeroen 13分钟前

完全从代码中删除了散列,现在没问题,它使用password_verify($ client_current_password,$ db_hash_pass)。

谢谢jeroen的推动,你让我这样做:D