我的登录功能无法验证我更改的密码

时间:2016-11-25 21:18:55

标签: php database

我在网上放了一个忘记密码系统,它正在运行。密码已在数据库中更改。但后来我无法登录。 password_verify无法验证新密码。我错过了什么?

这是我的forgetpass.php

 //Password submiting
        case 3:
            //we are submitting a new password (only for encrypted)
            if ($_POST['userID'] == '' || $_POST['key'] == '') header("location: login.php");
            if (strcmp($_POST['pw0'],$_POST['pw1']) != 0 || trim($_POST['pw0']) == '')
            {
                $error = true;
                $show = 'recoverForm';
            } else {
                $error = false;
                $show = 'recoverSuccess';
                updateUserPassword($_POST['userID'],$_POST['pw0'],$_POST['key']);
            }
        break;
    }
}
       elseif (isset($_GET['a']) && $_GET['a'] == 'recover' && $_GET['email'] != "") {
    $show = 'invalidKey';
    $result = checkEmailKey($_GET['email'],urldecode(base64_decode($_GET['u'])));

case 'recoverForm': ?>
    <h2>Password Recovery</h2>
    <p>Welcome back, <?= getUserName($securityUser=='' ? $_POST['userID'] : $securityUser); ?>.</p>
    <p>In the fields below, enter your new password.</p>
    <?php if ($error == true) { ?><span class="error">The new passwords must match and must not be empty.</span><?php } ?>
    <form action="<?= $_SERVER['PHP_SELF']; ?>" method="post">
        <div class="fieldGroup"><label for="pw0">New Password</label><div class="field"><input type="password" class="input" name="pw0" id="pw0" value="" maxlength="20"></div></div>
        <div class="fieldGroup"><label for="pw1">Confirm Password</label><div class="field"><input type="password" class="input" name="pw1" id="pw1" value="" maxlength="20"></div></div>
        <input type="hidden" name="subStep" value="3" />
        <input type="hidden" name="userID" value="<?= $securityUser=='' ? $_POST['userID'] : $securityUser; ?>" />
        <input type="hidden" name="key" value="<?= $_GET['email']=='' ? $_POST['key'] : $_GET['email']; ?>" />
        <div class="fieldGroup"><input type="submit" value="Submit" style="margin-left: 150px;" /></div>
        <div class="clear"></div>
    </form>

这是我的functions.php(具有登录和恢复通行证的功能)

function login($email, $password, $mysqli) {
    // Using prepared statements means that SQL injection is not possible. 

    if ($stmt = $mysqli->prepare("SELECT id, username, password 
        FROM users
       WHERE email = ?
        LIMIT 1")) {
        $stmt->bind_param('s', $email);  // Bind "$email" to parameter.
        $stmt->execute();    // Execute the prepared query.
        $stmt->store_result();

        // get variables from result.
        $stmt->bind_result($user_id, $username, $db_password);
        $stmt->fetch();

        if ($stmt->num_rows == 1) {
            // If the user exists we check if the account is locked
            // from too many login attempts 

            if (checkbrute($user_id, $mysqli) == true) {
                // Account is locked 
                // Send an email to user saying their account is locked
                return false;
            } else {
                // Check if the password in the database matches
                // the password the user submitted. We are using
                // the password_verify function to avoid timing attacks.
                if (password_verify($password, $db_password)) {
                    // Password is correct!
                    // Get the user-agent string of the user.
                    $user_browser = $_SERVER['HTTP_USER_AGENT'];
                    // XSS protection as we might print this value
                    $user_id = preg_replace("/[^0-9]+/", "", $user_id);
                    $_SESSION['user_id'] = $user_id;
                    // XSS protection as we might print this value
                    $username = preg_replace("/[^a-zA-Z0-9_\-]+/", 
                                                                "", 
                                                                $username);
                    $_SESSION['username'] = $username;
                    $_SESSION['email'] = $email;
                    $_SESSION['login_string'] = hash('sha512', 
                              $db_password . $user_browser);
                    // Login successful.
                    return true;
                } else {
                    // Password is not correct
                    // We record this attempt in the database
                    $now = time();
                    $mysqli->query("INSERT INTO login_attempts(user_id, time)
                                    VALUES ('$user_id', '$now')");
                    return false;
                }
            }
        } else {
            // No user exists.
            return false;
        }
    }
}




function login_check($mysqli) {
    // Check if all session variables are set

    if (isset($_SESSION['user_id'], 
                        $_SESSION['username'],
                        $_SESSION['email'],
                        $_SESSION['login_string'])) {

        $user_id = $_SESSION['user_id'];
        $login_string = $_SESSION['login_string'];
        $username = $_SESSION['username'];
        $email= $_SESSION['email'];

        // Get the user-agent string of the user.
        $user_browser = $_SERVER['HTTP_USER_AGENT'];

        if ($stmt = $mysqli->prepare("SELECT password 
                                      FROM users
                                      WHERE id = ? LIMIT 1")) {
            // Bind "$user_id" to parameter. 
            $stmt->bind_param('i', $user_id);
            $stmt->execute();   // Execute the prepared query.
            $stmt->store_result();

            if ($stmt->num_rows == 1) {
                // If the user exists get variables from result.
                $stmt->bind_result($password);
                $stmt->fetch();
                $login_check = hash('sha512', $password . $user_browser);

                if (hash_equals($login_check, $login_string) ){
                    // Logged In!!!! 
                    return true;
                } else {
                    // Not logged in 
                    return false;
                }
            } else {
                // Not logged in 
                return false;
            }
        } else {
            // Not logged in 
            return false;
        }
    } else {
        // Not logged in 
        return false;
    }
}

function checkUNEmail($uname,$email)
{
    global $mysqli;
    $error = array('status'=>false,'userID'=>0);
    if (isset($email) && trim($email) != '') {
        //email was entered
        if ($stmt = $mysqli->prepare ("SELECT `ID` FROM `users` WHERE `Email` = ? LIMIT 1"))
        {
            $stmt->bind_param('s',trim($email));
            $stmt->execute();
            $stmt->store_result();
            $numRows = $stmt->num_rows();
            $stmt->bind_result($userID);
            $stmt->fetch();
            $stmt->close();
            if ($numRows >= 1) return array('status'=>true,'userID'=>$userID);
        } else { return $error; }
    } elseif (isset($uname) && trim($uname) != '') {
        //username was entered
        if ($stmt = $mysqli->prepare("SELECT `ID` FROM `users` WHERE Username = ? LIMIT 1"))
        {
             $stmt->bind_param('s',trim($uname));
             $stmt->execute();
             $stmt->store_result();
            $numRows =  $stmt->num_rows();
             $stmt->bind_result($userID);
             $stmt->fetch();
             $stmt->close();
            if ($numRows >= 1) return array('status'=>true,'userID'=>$userID);
        } else { return $error; }
    } else {
        //nothing was entered;
        return $error;
    }
}



function sendPasswordEmail($userID)
{
    global $mysqli;
    if ($stmt = $mysqli->prepare("SELECT `Username`,`Email`,`Password` FROM `users` WHERE `ID` = ? LIMIT 1"))
    {
        $stmt->bind_param('i',$userID);
        $stmt->execute();
        $stmt->store_result();
        $stmt->bind_result($uname,$email,$pword);
        $stmt->fetch();
        $stmt->close();
        $expFormat = mktime(date("H"), date("i"), date("s"), date("m")  , date("d")+3, date("Y"));
        $expDate = date("Y-m-d H:i:s",$expFormat);
        $key = md5($uname . '_' . $email . rand(0,10000) .$expDate . PW_SALT);
        if ($stmt = $mysqli->prepare("INSERT INTO `recoveryemails_enc` (`UserID`,`Key`,`expDate`) VALUES (?,?,?)"))
        {
             $stmt->bind_param('iss',$userID,$key,$expDate);
            $stmt->execute();
             $stmt->close();
            $passwordLink = "<a href=\"?a=recover&email=" . $key . "&u=" . urlencode(base64_encode($userID)) . "\">http://www.oursite.com/forgotPass.php?a=recover&email=" . $key . "&u=" . urlencode(base64_encode($userID)) . "</a>";
            $message = "Dear $uname,\r\n";
            $message .= "Please visit the following link to reset your password:\r\n";
            $message .= "-----------------------\r\n";
            $message .= "$passwordLink\r\n";
            $message .= "-----------------------\r\n";
            $message .= "Please be sure to copy the entire link into your browser. The link will expire after 3 days for security reasons.\r\n\r\n";
            $message .= "If you did not request this forgotten password email, no action is needed, your password will not be reset as long as the link above is not visited. However, you may want to log into your account and change your security password and answer, as someone may have guessed it.\r\n\r\n";
            $message .= "Thanks,\r\n";
            $message .= "-- Our site team";
            $headers = '';
            $headers .= "From: Our Site <webmaster@oursite.com> \n";
            $headers .= "To-Sender: \n";
            $headers .= "X-Mailer: PHP\n"; // mailer
            $headers .= "Reply-To: webmaster@oursite.com\n"; // Reply address
            $headers .= "Return-Path: webmaster@oursite.com\n"; //Return Path for errors
            $headers .= "Content-Type: text/html; charset=iso-8859-1"; //Enc-type
            $subject = "Your Lost Password";
            @mail($email,$subject,$message,$headers);
            return str_replace("\r\n","<br/ >",$message);
        }
    }
}

function checkEmailKey($key,$userID)
{
     global $mysqli;
    $curDate = date("Y-m-d H:i:s");
    if ($stmt = $mysqli->prepare("SELECT `UserID` FROM `recoveryemails_enc` WHERE `Key` = ? AND `UserID` = ? AND `expDate` >= ?"))
    {
        $stmt->bind_param('sis',$key,$userID,$curDate);
        $stmt->execute();
        $stmt->execute();
        $stmt->store_result();
        $numRows = $stmt->num_rows();
        $stmt->bind_result($userID);
        $stmt->fetch();
        $stmt->close();
        if ($numRows > 0 && $userID != '')
        {
            return array('status'=>true,'userID'=>$userID);
        }
    }
    return false;
}

function updateUserPassword($userID,$password,$key)
{
     global $mysqli;
    if (checkEmailKey($key,$userID) === false) return false;
    if ($stmt = $mysqli->prepare("UPDATE `users` SET `Password` = ? WHERE `ID` = ?"))
    {
         $password = password_hash($password, PASSWORD_BCRYPT);
        $stmt->bind_param('si',$password,$userID);
        $stmt->execute();
        $stmt->close();
        $stmt = $mysqli->prepare("DELETE FROM `recoveryemails_enc` WHERE `Key` = ?");
        $stmt->bind_param('s',$key);
        $stmt->execute();
    }
}

function getUserName($userID)
{
    global $mysqli;
    if ($stmt = $mysqli->prepare("SELECT `Username` FROM `users` WHERE `ID` = ?"))
    {
        $stmt->bind_param('i',$userID);
        $stmt->execute();
        $stmt->store_result();
        $stmt->bind_result($uname);
        $stmt->fetch();
        $stmt->close();
    }
    return $uname;
}

在注册过程中创建传递的代码

// Create hashed password using the password_hash function.
        // This function salts it with a random salt and can be verified with
        // the password_verify function.
        $password = password_hash($password, PASSWORD_BCRYPT);

        // Insert the new user into the database 
        if ($insert_stmt = $mysqli->prepare("INSERT INTO users (username, email, password) VALUES (?, ?, ?)")) {
            $insert_stmt->bind_param('sss', $username, $email, $password);

1 个答案:

答案 0 :(得分:1)

好的,我想我已经发现了这个问题。我相信这一行需要你注意:

$login_check = hash('sha512', $password . $user_browser);

你实际上是使用password_hash和BCRYPT创建了一个哈希,所以我不认为创建一个sha512哈希并比较它会让你走得很远。验证使用password_hash创建的哈希的正确方法是使用password_verify。请参阅此示例from the PHP documentation on password_verify()

if (password_verify('rasmuslerdorf', $hash)) {
  echo 'Password is valid!';
} else {
  echo 'Invalid password.';
}

请注意

  

password_hash()返回算法,cost和salt作为返回哈希的一部分。因此,验证哈希所需的所有信息都包含在其中。这允许验证功能验证散列,而无需为盐或算法信息单独存储。

注册前后和pw更新

$password = '<PUT PASSWORD OF NEW USER HERE>';
$query = 'select password hash from users where id = <PUT ID OF NEW USER HERE>';
$res = mysqli_query($db, $query);
echo $row['hash'].' '.((password_verify($password, $row['hash']))?'hash is good!':'no, no match on hash').'<br>';

注册后检查以确保哈希是好的,然后在更新密码后进行检查。