注册&登录密码哈希方法相同但不起作用

时间:2014-04-22 21:41:43

标签: php mysql login hash pdo

我在这里看到类似的问题,但我不认为答案适用于我,如果他们这样做我很抱歉..

下面是包含两个过程的代码片段:

注意:登录和注册完全正常,没有散列元素。

if (isset($_POST['username']) && ($_POST['password'])) {
    $username = trim($_POST['username']);
    $username = strtolower($username);
    $password = trim($_POST['password']);
    $salt = hash('md5', "$username");
    $password = hash('sha256', "$password"."$salt");

    $stmt = $dbh->prepare("SELECT `id` FROM `1_users` WHERE username=? AND password=? LIMIT 1");
    $stmt->bindValue(1, $username, PDO::PARAM_STR);
    $stmt->bindValue(2, $password, PDO::PARAM_STR);
    $stmt->execute();
    if ($stmt->rowCount()) {
        // Match
        $results = $stmt->fetch(PDO::FETCH_ASSOC);
        $_SESSION['id'] = $results['id'];
        $_SESSION['logged_in'] = true;
        $_SESSION['ip'] = hash('sha1', "{$_SERVER['REMOTE_ADDR']}");
        header ("location: account.php");
    }
    else {
        $error = 'Invalid username/password!';
    }
}

if (isset($_POST['register'])) {
    // check for all fields..
    if ((empty($_POST['r_username'])) || (empty($_POST['r_password'])) || (empty($_POST['re_password'])) || (empty($_POST['email']))) {
        $r_error = 'One of the fields was empty.';
    }

    $stmt = $dbh->prepare("SELECT `username` FROM `1_members` WHERE `username`=? LIMIT 1");
    $username = strtolower($_POST['r_username']);
    $username = trim($username);
    $stmt->bindValue(1, $username, PDO::PARAM_STR);
    $stmt->execute();
    $row = $stmt->rowCount();
    if ($row) {
        $r_error = 'that username is already in use';
    }
    else if (($_POST['r_password']) !== ($_POST['re_password'])) {
        $r_error = 'The passwords did not match.';
    }
    else if (strlen($_POST['r_username']) <= '3') {
        $r_error = 'username too short - needs to be 4 more charicters.';
    }
    else if (strlen($_POST['r_password']) <='5'){
        $r_error = 'password not long enough, please make it 6-255 charicters or more.';
    }
    else {
        // woohoo lets make the account 
        $password = trim($_POST['r_password']);
        $salt = hash('md5', "$username");
        $password = hash('sha256', "$password"."$salt");
        $email = trim($_POST['email']);

       $stmt = $dbh->prepare("INSERT INTO `1_members` (`username`, `password`, `email`) VALUES(?,?,?)");
       $stmt->bindValue(1,$username,PDO::PARAM_STR);
       $stmt->bindValue(2,$password,PDO::PARAM_STR);
       $stmt->bindValue(3,$email,PDO::PARAM_STR);
       $stmt->execute();
       $_SESSION['id'] = $dbh->lastInsertId(); 
       $_SESSION['logged_in'] = true;
       $_SESSION['ip'] = hash('sha1', "{$_SERVER['REMOTE_ADDR']}");

       if ($_SESSION['active_cart']) {
           header ("location: cart.php");
       }
       else {
           header ("location: account.php");
       }
    }
}

在将哈希添加到密码之前,它正常运行,我不确定我的问题是什么。

调试:

username: admin1 password: admin1


登录程序将密码转为:927364bb72cee168bd52c45a5d131b5923e2926eb6e8f0f46d6d7e5765cc3401

注册程序创建密码为: 927364bb72cee168bd52c45a5d131b5923e2926eb6e8f0f46d6d7e5765cc3401

他们匹配所以出了什么问题?

此外,如果我在这里有错误的想法,或者如果我忽略了重要的安全措施,请告知更好的方法。

另外,我并不那么担心电子邮件验证,而且我完全清楚有很多预制的snipplet可用于验证电子邮件,我将在以后进行此操作。

任何CC都非常受欢迎。

编辑:该脚本返回“无效的用户名/密码组合”。

2 个答案:

答案 0 :(得分:1)

我怀疑散列密码的数据库字段太小,该字段必须能够存储64个字符。

即使您可以解决此问题,您也有一个不安全的方案来存储密码(SHA256对于散列密码来说太快了)。看看PHP函数password_hash(),它将生成一个BCrypt哈希并负责生成安全盐。盐将成为生成的62个字符串的一部分,因此无需单独存储盐。对于较旧的PHP版本,还存在compatibility pack

// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);

// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);

这也意味着您无法直接在SQL语句中验证密码,而是从数据库中读取哈希值(通过用户名),然后使用此哈希值调用password_verify()。

答案 1 :(得分:0)

可能是,PDOStatement :: rowCount()在SELECT查询上执行时不会返回“1”。看看这里:

http://www.php.net/manual/en/pdostatement.rowcount.php

(特别是实施例#2)