2

我正在创建一个需要用户授权才能访问某些功能的网站。我目前正在研究用户如何创建帐户以及如何利用会话来授权他们的登录。用户信息存储在名为 user 的 MySQL 表中,其中可能包括用户名和密码的引用。

我一直在阅读密码散列/盐以确保安全,并希望一些 PHP 大师的输入,考虑到我仍然是该语言的新手。

我写了以下脚本:

define('SALT_LENGTH', 6);

function generateHash($plaintext, $salt==null){
    if($salt == null){
        $salt = substr(md5(uniqid(rand(), true)), 0, SALT_LENGTH);
    }
    else{
        $salt = substr($salt, 0, SALT_LENGTH);
    }

    return $salt . sha1($salt . $plaintext);
}
?>

这是一个用于生成带有盐的哈希的函数。

$username = $_POST['username'];
$password = generateHash($_POST['password']);
try{
    $stmt = $pdo->prepare(INSERT INTO user VALUES (:username, :password, :location,     :email, :name);
}catch(PDOException $e){
    echo $e->getMessage();
}
    $stmt->execute(array(':username'=>$username, 
                         ':password'=>$password, 
                         ':location'=>$location, 
                         ':email'=>$email, 
                         ':name'=>$name);

这是创建帐户的脚本的重要部分

if(isset($_POST)){
    //if form was submitted

    $username = $_POST['username'];
    $password = generateHash($_POST['password']);

    session_start();

    $user = 'root';
    $pass = null;
    $pdo = new PDO('mysql:host=localhost; dbname=divebay;', $user, $pass);

    try{
        $stmt = $pdo->prepare('SELECT username FROM user WHERE username =     :username AND password = :password');
        $stmt->execute(array(':username'=>$username,
                             ':password'=>$password);

        if($stmt->fetch(PDO::FETCH_ASSOC)){
            echo 'match';
        }
        else{
            echo 'nomatch';
        }

这是在数据库中查找用户的登录会话脚本

我的主要问题是这种散列/盐看起来会起作用吗?我对用于在一个实例中创建加密的哈希(创建帐户)如何能够与在不同实例中创建的哈希一起工作感到困惑。此外,我试图创建的内容的复杂性是否适合一个可能永远不会正确部署的相对简单的软件项目?

任何其他关于我的脚本错误的建议也将不胜感激(我需要批评)。

4

3 回答 3

2

我对您的建议是寻找一个为您执行此操作的库/框架。许多框架会自动并正确地为您处理这类事情,通常包括基于角色的授权。身份验证和授权并不是很难做到,但它们已经足够难了,除非您将其作为学习练习,否则您应该尽量避免自己做。

至于您的代码的正确性,我认为您需要使用与您帐户名上存储的密码匹配的盐来比较密码。您应该在数据库中查找给定用户名的密码哈希,从该密码哈希(您正确附加)中检索盐,然后在提供的密码上使用检索到的盐来获取哈希。然后,您将哈希与存储的哈希进行字符串比较以进行身份​​验证。

我不太了解 PHP,但我确信存在一个可以为您处理此问题的库。

于 2012-07-23T15:31:19.757 回答
1

看起来不对,当没有提供盐时,您会随机选择一个不存储的盐。

在散列之后,您将尝试记录您的用户,您将对提供的密码进行散列,计算它的散列并将其与存储在数据库中的密码进行检查。如果您的散列可以随时间变化,则这不是散列。

您必须使用常量盐(可能比六个字符长的盐长),或者将生成的盐存储在数据库中。您必须能够为完全相同的输入计算完全相同的哈希值。

于 2012-07-23T15:23:36.750 回答
1

只要generateHash在登录时同时调用密码创建和密码检查,由于相同的输出(假设相同的输入),此哈希将正常运行。

然而,就目前而言,情况似乎并非如此。您需要将$salt(因为它是随机生成的)存储在数据库中并在检查期间检索它。

于 2012-07-23T15:23:44.190 回答