通过电子邮件获取用户并检查密码的代码有什么问题?

时间:2015-11-08 23:07:46

标签: php database

我是php的新手,我正在实施一个登录系统,用户输入电子邮件和密码并检查它们是否存在于数据库中(phpmyadmin中的mysql)

当用户首次注册时,使用此功能加密密码:

/**
 * Encrypting password
 *
 * @param
 *          password
 *          returns salt and encrypted password
 */
public function hashSSHA($password) {
    $salt = sha1 ( rand () );
    $salt = substr ( $salt, 0, 10 );
    $encrypted = base64_encode ( sha1 ( $password . $salt, true ) . $salt );
    $hash = array (
            "salt" => $salt,
            "encrypted" => $encrypted 
    );
    return $hash;
}

作为解密密码的密钥的salt参数存储在数据库中,其中包含用户信息,解密代码为:

/**
 * Decrypting password
 *
 * @param
 *          salt, password
 *          returns hash string
 */
public function checkhashSSHA($salt, $password) {
    $hash = base64_encode ( sha1 ( $password . $salt, true ) . $salt );

    return $hash;
}

当我去输入用户并输入电子邮件和密码时,密码被解密。

/**
 * Get user by email and password
 */
public function getUserByEmailAndPassword($email, $password) {
    $stmt = $this->conn->prepare ( "SELECT * FROM users WHERE email = ?" );

    $stmt->bind_param ( "s", $email );

    if ($stmt->execute ()) {
        $user = $stmt->get_result ()->fetch_assoc ();
        $stmt->close ();
        $salt = $user ["salt"];
        $hash = $this->checkhashSSHA ( $salt, $user ["encrypted_password"] );
        if ($hash == $password) {
            return $user;
        } else {
            return NULL;
        }
    } else {
        return NULL;
    }
}

问题是当用户输入正确的电子邮件和密码时,此代码仍返回NULL并且我怀疑处理密码部分有问题。

3 个答案:

答案 0 :(得分:1)

Siguza的回答是正确的,但你对他的回答的评论反映了一个非常合理的混淆,因为checkhashSSHA()函数的名称有点误导(即它的名称与其行为不匹配)。以“check”开头的函数名应该返回一个布尔值。我建议将其改为:

/**
 * Decrypting password
 *
 * @param
 *          password, hash, salt
 *          returns boolean
 */
public function checkhashSSHA($password, $hash, $salt) {
    $hash2 = base64_encode ( sha1 ( $password . $salt, true ) . $salt );

    return ($hash == $hash2) ;
}

现在改变这两行:

$hash = $this->checkhashSSHA ( $salt, $user ["encrypted_password"] );
if ($hash == $password) {

到这一行:

if (checkhashSSHA($password, $user["encrypted_password"], $salt)) {

现在它更清晰,更易于使用,其行为与其名称相符。但是,如果您希望增强代码中的命名,可以参考以下建议:

  • checkhashSSHA()更改为compareHashSSHA()
  • 将数据库中的encrypted_password更改为hashed_password

更重要的是,sha1哈希算法有点旧,不太安全。我建议将其更改为更安全的散列,如sha512。查看this并阅读Kai Petzke的评论,了解完整的故事。

答案 1 :(得分:0)

问题在于以下两点:

$hash = $this->checkhashSSHA ( $salt, $user ["encrypted_password"] );
if ($hash == $password) {

首先,您正在散列已经哈希的密码,而不是明文密码。
然后你将“散列哈希”与明文密码进行比较 所以你正在做hash(hash(pw)) == pw,它应该是hash(pw) == hash(pw)

您只需要交换$user ["encrypted_password"]$password

$hash = $this->checkhashSSHA ( $salt, $password );
if ($hash == $user ["encrypted_password"]) {

答案 2 :(得分:-1)

我建议你不要使用sshhash函数来查看php函数password_verify()

在此检查有关该功能及相关功能的文档: http://php.net/manual/en/function.password-verify.php