我有一个想法让系统登录用户并验证他们在页面上的登录。
我意识到那里有很多系统,但我主要是好奇我的想法是否有用。我已经进行了一些挖掘,但大多数结果似乎都遗漏了我一直认为重要的做法(如密码加密等)。我可能会更加努力地寻找预制解决方案,因为它可能更安全,但我还没有真正研究过应用程序安全性,并希望得到一些反馈。
当用户登录时,他们的姓名和密码将根据数据库进行验证,密码使用 SHA256 和随机生成的 salt 进行加密,即整个字符串(salt 和加密密码均为 128 个字符。长)。这是密码验证代码:
function ValidatePassword($password, $correctHash)
{
$salt = substr($correctHash, 0, 64); //get the salt from the front of the hash
$validHash = substr($correctHash, 64, 64); //the SHA256
$testHash = hash("sha256", $salt . $password); //hash the password being tested
//if the hashes are exactly the same, the password is valid
return $testHash === $validHash;
}
如果登录有效,则为他们分配一个令牌。该令牌类似于密码加密,但存储了加密的纪元以及另一个随机盐。令牌、登录时间、过期时间和用户名存储在数据库中,用户名和令牌作为会话信息传输。
这是创建令牌的代码:
function loginUser($email)
{
$thetime = time();
$ip = $_SERVER['REMOTE_ADDR'];
$dbuser="///";
$dbpass="///";
$dbtable="tokens";
mysql_connect(localhost,$dbuser,$dbpass);
mysql_select_db("///") or die( "Unable to select database");
//Generate a salt
$salt = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM));
//Hash the salt and the current time to get a random token
$hash = hash("sha256", $salt . $password);
//Prepend the salt to the hash
$final = $salt . $hash;
$exptime = $thetime + 3600;
//Store this value into the db
$query = "INSERT INTO `spanel`.`tokens` VALUES ('$final', $thetime, $exptime, $thetime, '$ip', MD5('$email') )";
mysql_query($query) or die ("Could not create token.");
//Store the data into session vars
$_SESSION['spanel_email'] = $email;
$_SESSION['spanel_token'] = $final;
return true;
}
当他们到达一个页面时,他们拥有的令牌和用户名将根据数据库进行检查。如果检查良好,则更新过期时间并加载页面。这是代码:
function validateUser($page)
{
//Grab some vars
$thetime = time();
$ip = $_SERVER['REMOTE_ADDR'];
$token = $_SESSION['spanel_token'];
$email = $_SESSION['spanel_email'];
$dbuser="///";
$dbpass="///";
$dbtable="tokens";
mysql_connect(localhost,$dbuser,$dbpass);
mysql_select_db("///") or die( "Unable to select database");
//Global var
//Get the var for token expire
$token_expire = 3600;
//Validate the token
$query = "SELECT * FROM `tokens` WHERE `token` LIKE '$token' AND `user_id` LIKE MD5('$email') AND `exp` > $thetime";
$result = mysql_query($query) or die(mysql_error());
//Check if we have a valid result
if ( mysql_num_rows($result) != 1 ) {
//Logout the user
//Destroy the session
session_destroy();
//Redirect
header("location: /spanel/login.php?denied=1");
exit();
//(Since the token is already invalid, there's no reason to reset it as invalid)
}
$row = mysql_fetch_assoc($result);
//Update the token with our lastseen
$newexp = $thetime + $token_expire;
$query = "UPDATE `spanel`.`tokens` SET `exp` = $newexp, `lastseen_ip` = $thetime, `lastseen_ip` = '$ip' WHERE `token` LIKE '$token'";
mysql_query($query);
}
感谢反馈(好的和坏的)。就像我说的,我没有做太多的安全工作,希望得到指点。
编辑:我担心我高估了我有效创建登录系统的能力。这么说,我理解你是否决定停止试图找出这个可能是有缺陷的想法的混乱局面。
不过,这里是登录页面的 php 代码。(在这里所说的之后,我意识到只是发布密码是一个很大的禁忌)。
$email = $_POST['email'];
$password = $_POST['password'];
$dbuser="///";
$dbpass="///";
$dbtable="///";
mysql_connect(localhost,$dbuser,$dbpass);
mysql_select_db("spanel") or die( "Unable to select database");
$query = "SELECT * FROM users WHERE `email` LIKE '$email'";
$result=mysql_query($query) or die(mysql_error());
$num=mysql_num_rows($result);
$row = mysql_fetch_array($result);
if ( ValidatePassword($password, $row['hash']) == true ) {
loginUser($email);
header("location: /spanel/index.php");
} else {
echo "<p>Login Failed.</p>";
}
这是创建帐户时生成密码盐和哈希的位。
function HashPassword($password)
{
$salt = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM)); //get 256 random bits in hex
$hash = hash("sha256", $salt . $password); //prepend the salt, then hash
//store the salt and hash in the same string, so only 1 DB column is needed
$final = $salt . $hash;
return $final;
}
感谢您的反馈,我很高兴在这里发现了我缺乏知识的问题,而不是在攻击之后。