即时创建一个需要用户授权才能访问某些功能的网站。我目前正在研究用户如何创建帐户以及如何利用会话来授权他们的登录。用户信息存储在名为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';
}
这是用于在数据库中查找用户的登录会话脚本
我的主要问题是这个哈希/盐看起来会起作用吗?我很困惑,在一个实例(创建acct)中用于创建加密的哈希将如何使用在不同实例中创建的哈希。此外,我试图创建适合于相对简单的软件项目的复杂性是否可能永远不会被正确部署?
我的剧本错误的任何其他建议也将受到赞赏(我需要批评)。
答案 0 :(得分:2)
我给你的建议是找一个为你做这个的图书馆/框架。许多框架会自动而正确地为您处理此类事情,通常包括基于角色的授权。身份验证和授权并不是非常难以正确完成,但它们很难以至于您应该尽量避免自己做,除非您将其作为学习练习。
至于代码的正确性,我认为您需要使用与您帐户名称中存储的密码匹配的salt来比较密码。您应该查找数据库中给定用户名的密码哈希值,从该密码哈希值(您正确附加)中检索salt,然后使用提供的密码上的检索到的盐来获取哈希值。然后,您可以将哈希值与存储的哈希值进行字符串比较以进行身份验证。
我不太了解PHP,但我确信存在一个可以为你处理这个问题的库。
答案 1 :(得分:1)
看起来不对,当没有提供盐时,你会随机取一个你不存储的盐。
在进行散列后,您将尝试记录您的用户,您将对提供的密码进行散列,计算它的散列并将其与存储在数据库中的密码进行核对。如果你的哈希值随时间变化,那么这不是哈希值。
您要么使用常量盐(可能比六个字符长的盐长),要么将生成的盐存储在数据库中。您必须能够为完全相同的输入计算完全相同的哈希值。
答案 2 :(得分:1)
只要在登录时同时调用密码创建和密码检查generateHash
,由于输出相同(假设输入相同),此哈希将正常运行。
然而,截至目前,情况似乎并非如此。您需要将$salt
(因为它是随机生成的)存储在数据库中,并在检查期间检索它。