1

我最近添加了一个使用存储在成员表中的唯一盐的类。这是我使用盐之前的登录脚本:

    $sql = 'SELECT id, username FROM member WHERE username = ? AND pass = ?';

    $result = $this->DB->query($sql, array($username, $pass));
    foreach($result as $record) {
        $user = [
    "id" => $record['id'],
    "username" => $record['name']];
}

if (empty($user)) {
        // Display errors
    } else {
            // Login by sending the array of data to login function
        self::login($user);
    }

现在,我也想买盐。有什么方法可以在不使用超过 1 个查询的情况下做到这一点?我可以通过从查询开始以获取用户通行证和加盐来使其工作,但有没有更好的方法。感觉有点像黑客攻击,还是根本无法避免?

4

2 回答 2

4

您可以这样做(假设pass创建为MD5($salt . $password)并且您saltmember表中命名了列):

$sql = 'SELECT id, username FROM member WHERE username = ?
           AND pass = MD5(CONCAT(member.salt, ?))';

这样,MySQL 直接检查在CONCAT-ing插入密码和盐之后创建的存储散列。

于 2012-12-05T10:01:22.613 回答
1

您的数据库不提供密码的安全散列函数,MD5任何其他快速散列函数都不应该用于散列密码。

这就是为什么您无法通过单个查询来检查您的密码哈希的原因。相反,您可以对数据库进行一次查询,获取密码哈希:

SELECT username, pass FROM member WHERE username = ?

现在您可以pass使用 php 进行检查,而不是使用 SQL 进行检查。这样您也只需要 1 个查询,但可以使用安全哈希算法。盐可以pass与哈希值一起存储在同一字段中。

推荐使用BCrypt。PHP 5.5 将拥有自己的功能password_hash()password_verify()准备就绪,以简化此任务。有一个适用于 PHP 5.3/5.4 的兼容包,可在password_compat下载。

于 2012-12-05T11:53:13.860 回答