我遇到了一些代码问题并且很容易理解为什么会出错
//Searches the database for the username
$mysqli_username = mysqli_query($mysqli, "SELECT username FROM ajbs_users WHERE username=`".$username."`");
// if name does not exist
if ($mysqli_username == null)
{
echo "<p>Username was inccorect, or user does not exist</p>";
}
else //if username is correct
{
//finds and stores password of the user
$mysqli_userPassword = mysqli_query($mysqli, "SELECT password FROM ajbs_users WHERE password=`".$password."`");
if ($mysqli_userPassword != $password) //checks password matches from user
{
echo "<p>Password was inccorrect</p>";
}
else
{
//Login
echo "<p>You have been logged in";
// Re directs to other page after creating a session
}
}
脚本不断输出“密码不正确”声明。
答案 0 :(得分:2)
您的代码存在许多问题:
mysqli_query()不返回数据库中的行,它返回资源,您可以从中获取数据库中的行。否则,如果查询产生解析错误或执行错误,则返回 false 。您需要检查这些错误情况。
或者使用mysqli_report(MYSQLI_REPORT_STRICT)配置mysqli以在错误时抛出异常(如果您知道如何使用异常进行编程)。
您正在使用价值$ username和$ password的后退。反向标记用于分隔表名称和列名称等标识符。对于字符串值和日期值,请使用单引号。对于字符串和日期,双引号在默认情况下与单引号相同。但是,如果将MySQL设置为ANSI模式,则可以更改,然后使用双引号作为标识符。请参阅MySQL's different quote marks
您正在将变量直接插入到SQL表达式中,除非您非常小心地将它们转义,否则这是不安全的。这就是SQL注入的发生方式。阅读What is SQL injection?和How can I prevent SQL injection in PHP?您应该使用预准备语句并使用参数向查询添加动态元素。
请记住,如果使用参数,引用问题就会消失。您不会在参数周围添加任何类型的引号。 使用参数比将变量插入字符串更容易,也更安全。
您的逻辑或应用程序设计存在一些问题:
您检查了是否存在用户名。如果是,则检查密码是否存在。但是在您的代码中,密码不一定由相同的用户名使用。您的代码不会检查相同的用户是否拥有该密码,只检查 any 用户拥有该密码。
这意味着如果我可以使用我知道的密码注册一个用户名,我可以破解您的网站,比如'xyzzy'。然后我可以使用密码'xyzzy'登录作为任何其他用户名。
告诉用户用户名或密码是否不正确并不是一个好的安全措施。他们应该只被告知登录失败。如果他们是黑客,那么他们知道他们是在正确的轨道上是有用的,也就是说,他们选择了有效的用户名,他们只需要猜测密码。您可能希望记录自己的故障排除信息,但在向用户报告时更加模糊。
您不应存储纯文本密码。存储密码的哈希值。还为每个用户存储随机盐,并在哈希计算中使用它。请参阅You're Probably Storing Passwords Incorrectly和What data type to use for hashed password field and what length?
如果您在一个查询中比较用户名和密码,则可以使用一个查询而不是两个查询执行此搜索。我在WHERE子句中搜索用户名,然后将存储的密码哈希的布尔比较结果与用户输入的哈希值一起返回。
所以这就是我如何写它,记住上面的所有要点。
/*
* Search the database for the username, and report if the password matches
*/
$sql = "SELECT (password = SHA2(CONCAT(?, salt), 256)) AS password_matches
FROM ajbs_users WHERE username = ?";
if (($stmt = $mysqli->prepare($sql)) === false) {
trigger_error($mysqli->error, E_USER_ERROR);
}
$stmt->bind_param("ss", $password, $username);
if ($stmt->execute() === false) {
trigger_error($stmt->error, E_USER_ERROR);
}
$stmt->bind_result($password_matches);
if ($stmt->fetch()) {
if ($password_matches) {
echo "<p>You have been logged in";
// Re directs to other page after creating a session
} else {
error_log("Login attempted with user '$username', but password was incorrect.");
}
} else {
error_log("Login attempted with user '$username', but user does not exist.");
}
// Tell the user only what they need to know.
echo "<p>Login failed. Username or password was incorrect</p>";