如果这个问题看起来很傻,我真的很抱歉。但是我几天来一直试图检查数据库中的username
和password
是否与我在html
页面中输入的内容相符...这是我的登录信息形式...
<form method="POST" action="Dashboard/Dashboard.php">
<div class="form-group md-form">
<!--<input type="email" class="form-control" id="email" value="" placeholder="Enter email address">-->
<i class="fa fa-user prefix grey-text"></i>
<input name="username" id="username" type="text" class="form-control" required>
<label for="defaultForm-email">Username</label>
</div>
<div class="form-group md-form">
<!--<input type="password" class="form-control" id="password" value="" placeholder="Enter password">-->
<i class="fa fa-lock prefix grey-text"></i>
<input name="password" id="password" type="password" class="form-control" required>
<label for="defaultForm-pass">Your password</label>
</div>
<div class="text-center">
<button type="reset" class="btn btn-amber btn-sm"><strong>Reset</strong></button>
<input type="submit" name="submit" id="submit" class="btn btn-green btn-sm" value="Sign in">
</div>
</form>
这是我在php
Dashboard.php
)
<?php
$servername = "localhost";
$username = "root";
$password = "";
$databaseName = "test";
$conn = mysqli_connect($servername, $username, $password, $databaseName);
$un = $_POST['username'];
$pw = $_POST['password'];
print $pass . "_" . $email;
$query = mysqli_query($conn, "SELECT log_username,log_password FROM login WHERE log_username='$un' AND log_password='$pw'");
$result_can = mysqli_query($conn, $query);
while ($row = mysql_fetch_assoc($result_can)) {
$check_username = $row['username'];
$check_password = $row['password'];
}
if ($un == $check_username && $pw == $check_password) {
$message = "ok";
echo "<script type='text/javascript'>alert('$message');</script>";
header("Location: Doctors.php");
} else {
$message = "No";
echo "<script type='text/javascript'>alert('$message');</script>";
header("Location: Doctors.php");
}
?>
我真的尝试了几千次,但无法弄清楚我哪里出错了......有人可以帮助我吗?
我知道我的代码对SQL注入是开放的,但我并不关心它,因为这是我需要向朋友展示的一个例子所以忽略那部分。
答案 0 :(得分:6)
Stack Overflow适用于“专业和发烧友程序员”。尊敬的是,你已经向我们展示了你的问题中的代码,这些代码甚至不值得任何一个名字。
StackOverflow人员对糟糕的安全代码没有太大的幽默感。你得到像你这样的代码的强烈反应,因为,Equifax,Ashley Madison和Adobe,以及被网络犯罪分子破解的所有其他地方。我们为什么要跳上你?因为我们不喜欢网络犯罪分子,我们不想让他们生活轻松。朋友不要让朋友做错密码安全。朋友不会向朋友展示严重不安全的密码验证码。
您的代码有什么问题?您将密码存储为纯文本,并且您很容易受到SQL注入攻击。我将解决第一个问题。
幸运的是,php具有良好的密码安全性。在这里阅读它们。 http://php.net/manual/en/faq.passwords.php使用它们。你如何处理密码?
$usersPassword = $_POST['password']);
$hash = password_hash( $usersPassword , PASSWORD_DEFAULT );
// you then store the username and the hash in your dbms.
// the column holding the hash should be VARCHAR(255) for future-proofing
// NEVER! store the plain text (unhashed) password in your database
当用户尝试登录时,您执行以下查询:
SELECT log_password FROM log_user WHERE log_username = TheUsernameGiven
然后,将检索到的密码放入名为$hash
的列中。
然后使用php's password_verify()
function检查您的用户刚给您的密码是否与您数据库中的密码相匹配。
最后,检查是否需要重新设置用户的密码,因为之前用于散列的方法已经过时了。
$usersPassword = $_POST['password']);
$valid = password_verify ( $usersPassword, $hash );
if ( $valid ) {
if ( password_needs_rehash ( $hash, PASSWORD_DEFAULT ) ) {
$newHash = password_hash( $usersPassword, PASSWORD_DEFAULT );
/* UPDATE the user's row in `log_user` to store $newHash */
}
/* log the user in, have fun! */
}
else {
/* tell the would-be user the username/password combo is invalid */
}
这个序列是未来的,因为如果旧的哈希方法太容易被网络攻击破解,它可以在以后重新密码。
答案 1 :(得分:1)
这里有几个问题,无论是在您的代码还是在思考过程中。让我们一路走下去:
$un = $_POST['username'];
$pw = $_POST['password'];
print $pass . "_" . $email;
print
行应该给你一个警告。变量$pass
和$email
不存在。您应删除该行,除非您尝试要执行的操作是打印$un
和$pw
。
$query = mysqli_query($conn, "SELECT log_username,log_password FROM login WHERE log_username='$un' AND log_password='$pw'");
无需同时选择用户名和密码列。如果匹配,则它们将始终与您已拥有的$un
和$pw
相同。您只是检查用户名和密码是否正确,因此选择单个列就足够了。最好是用户ID,但只有用户名就足够了。
请记住 - 假设查询成功执行 - $query
将包含mysqli_result
个对象。
$result_can = mysqli_query($conn, $query);
此行需要删除。你已经执行了你的查询,$query
就是它的结果,你在这里所做的事情毫无意义,应该给你一个警告,或者甚至是一个致命的错误。
while ($row = mysql_fetch_assoc($result_can)) {
$check_username = $row['username'];
$check_password = $row['password'];
}
if ($un == $check_username && $pw == $check_password) {
$message = "ok";
echo "<script type='text/javascript'>alert('$message');</script>";
header("Location: Doctors.php");
} else {
$message = "No";
echo "<script type='text/javascript'>alert('$message');</script>";
header("Location: Doctors.php");
}
您无法混合mysql_*
和mysqli_*
个功能。在这里使用mysql_fetch_assoc()
会给你一个致命的错误。您应该使用mysqli_fetch_assoc()
代替$query
代替$result_can
),但是:
由于您只关心是否有任何结果 ,因此整个部分可以更改为:
if (mysqli_num_rows($query) > 0) {
$message = "ok";
echo "<script type='text/javascript'>alert('$message');</script>";
header("Location: Doctors.php");
} else {
$message = "No";
echo "<script type='text/javascript'>alert('$message');</script>";
header("Location: Doctors.php");
}
这会带来其他问题,因为在回显header()
标记后,您无法使用<script>
重定向用户(您将收到“已发送的标头”错误)。如果您需要Javascript警报,请使用Javascript执行重定向。此外,$message
变量相当无用,您也可以将消息直接放入警报中:
if (mysqli_num_rows($query) > 0) {
echo "<script type='text/javascript'>alert('ok'); window.location.href='Doctors.php';</script>";
} else {
echo "<script type='text/javascript'>alert('No'); window.location.href='Doctors.php';</script>";
}
一旦你解决了这些问题的所有,你仍然有一些想法。
admin' AND 1 --
作为任何有效用户(例如“admin”)登录,或者如果我只想访问我可以使用any' OR 1 --
的用户名,并以表格中的第一个用户身份登录。查看准备好的陈述及其工作原理。这里的主要教训应该是:当你正在开发并且它不起作用时,总是检查错误日志以查看它是否包含任何提示并打开PHP的错误报告功能,这样你就可以看到你做错了什么吧在浏览器中。
答案 2 :(得分:1)
上面的评论提到了一些问题。
您使用mysqli_query()
调用查询,但尝试使用mysql_fetch_assoc()
获取结果。您不能混用这些不同的API。 mysql_*
函数不会使用您使用mysqli_connect()
打开的连接,反之亦然。选择一个MySQL扩展并坚持下去。
提示:根本不要使用mysql_*
。它已被弃用,已从PHP 7.0 +
只需搜索用户名,然后获取密码即可。如果您搜索 both ,则搜索将返回零行,除非使用了正确的密码。
你不想那样。您希望避免将明文密码放在SQL查询中。只需搜索用户名,然后获取存储的密码,然后将您获取的内容与用户输入密码进行比较。
如果从查询中获取零行,则永远不会设置$check_username
和$check_password
。然后在if语句中比较这些变量。不是致命的错误,而是糟糕的风格。
您似乎将用户输入(我认为是纯文本)直接与数据库中存储的内容进行比较。 You're Probably Storing Passwords Incorrectly.
相反,当您存储密码时,请先使用password_hash()。
我知道你说你不关心你的SQL注入漏洞,但这就像是一个电工,并说你不在乎你的电气面板上塞满了油性碎布。请务必在LinkedIn个人资料中发布您对安全的忽视,以便雇主知道应避免的人。
mysqli_report(MYSQLI_REPORT_STRICT); // enable exceptions
$conn = new mysqli($servername, $mysql_username, $mysql_password, $databaseName);
$log_username = $_POST['username'];
$log_password = $_POST['password'];
$sql = "SELECT log_username, log_password_hash FROM login WHERE log_username=?";
$stmt = $conn->prepare($sql);
$stmt->bind_param('s', $log_username);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
if (password_verify($log_password, $row['log_password_hash'])) {
$message = "ok";
// header must be called before any other output
header("Location: Doctors.php");
exit();
}
}
$message = "No";
// header must be called before any other output
header("Location: Doctors.php");