登录页面的准备语句问题
Posted
技术标签:
【中文标题】登录页面的准备语句问题【英文标题】:Problem With Prepared Statements for Login Page 【发布时间】:2020-05-24 13:50:03 【问题描述】:我正在尝试为我的网站创建登录页面。我从我建立的另一个网站复制并粘贴了这个,登录工作正常。我使用 echo 语句对其进行了测试,但是当我尝试登录时得到的只是登录页面的截断版本。它会在此代码粘贴到 html 代码中的位置截断。我已经看过很多次了,我的眼睛已经变成了对眼,所以我不确定我错过了什么!非常感谢任何帮助!
<?php
if($_SERVER['REQUEST_METHOD'] != 'POST')
echo '<form method="post" action="">
<p><label for="username">Username:</label><input type="text" name="username" id="username" title="username"></p>
<p><label for="password">Password:</label><input type="password" name="password" id="password" title="password"></p>
<p><input type="submit" name="login" id="login" value="Login"></p></form>';
else
$username = $_POST['username'];
$password = $_POST['password'];
$mysqli = new mysqli("","","","");
if($mysqli->connect_error)
exit('Error connecting to database');
else
$sql2 = "SELECT admin_id, admin_username, admin_password FROM adminlogin WHERE admin_username = ?";
if(($stmt = $mysqli->prepare($sql2)) === false)
error_log($mysqli->error);
error_log("SQL = [$sql2]");
die("Database error, contact site admin");
else
$stmt->bind_param("s", $username);
$stmt->execute();
$stmt->store_result();
if($stmt->store_result() === false)
error_log($stmt->error);
die("Database error, contact site admin.");
else
echo 'No error';
// test store
// bind param
// sql statement
// test connection
?>
</div>
<div class="col-1-3">
<h2>Search Blog</h2><br>
<form method="post" action="search.php" name="search" id="search">
<p><input type="text" name="searchinput" id="searchinput" title="search"></p>
<p><input type="submit" name="search" id="search" value="Search"></p>
</form>
<br>
<h2>About</h2>
<p>Hello and welcome to Cooking for Alaska: THM and Healthy Eating on a Budget! It is my prayer that you will find this blog useful in helping your family eat healthy while living on an Alaska-based budget. Groceries in Alaska are expensive, but feeding your family shouldn't be! Please enjoy my blog and feel free to contact me with any questions.</p>
<br>
<h2>Recent Blog Posts</h2>
<?php
include('includes/dblogin.php');
$sql = "SELECT * FROM recentposts_short ORDER BY post_datetime DESC LIMIT 3";
$result = mysqli_query($con, $sql);
if($result == false)
$mysql_error = mysqli_error($con);
echo '<p>There was an error. Please contact an administrator.</p>';
else
while($row=mysqli_fetch_assoc($result))
echo '<p><bold><a href="blog.php?id='.$row['post_title'].'">'.$row['post_title'].'</a></bold></p>';
echo '<p class="smallfont">'.$row['post_datetime'].'</p><br>';
?><br>
【问题讨论】:
也许您的数据库中没有您输入的用户名的行?这将使您的while($stmt->fetch())
循环执行零次,并且似乎没有输出指示未知用户。
顺便说一句,你应该更改你的 mysql 管理员密码,因为你已经将它发布在互联网上。
用户名有一行。我仔细检查了那个。是的,我更改了密码,但感谢您的额外提醒!
此时我的策略是在每个步骤中添加几行代码来调用error_log()
以输出有关已成功完成的操作的信息。然后查看您的 http 服务器错误日志以获取该输出。这是一种常见的 PHP 调试技术。
我得到了绑定结果,然后它退出了工作。我使用了var_dump()
,但当我走到那一步时,什么也没显示。
【参考方案1】:
我测试了您的代码,它可以正常工作。没有什么问题。
我建议尽管您说您仔细检查了数据库,但问题是此 PHP 代码连接到的数据库中不存在用户名。也许你检查了错误的数据库。
我按原样测试了您的代码,然后对其进行了一些重构。我想我会告诉你我写这个的方式:
这显示了error_log()
的使用,它输出到 http 错误文件。将技术错误消息输出到您可以阅读的位置是一个好习惯,但会在浏览器输出中呈现更用户友好的错误。您不想让您的用户感到困惑。
$mysqli = new mysqli("localhost","USER","PASSWORD","DB");
if ($mysqli->connect_error)
error_log($mysqli->connect_error);
die('Error connecting to database, contact site administrator');
将 SQL 放入变量中,以便在出现问题时将其输出到错误日志中。同样,用户不需要知道技术细节,他们只需要知道失败并且站点管理员需要修复它。
$sql = "
SELECT admin_id, admin_username, admin_password
FROM admin
WHERE admin_username = ?";
if (($stmt = $mysqli->prepare($sql)) === false)
error_log($mysqli->error);
error_log("SQL = [$sql]");
die("Database error, contact site administrator");
如果任何步骤出现问题,每个 mysqli 函数都会返回 false。你需要检查一下。
if ($stmt->bind_param("s", $username) === false)
error_log($stmt->error);
die("Database error, contact site administrator");
if ($stmt->execute() === false)
error_log($stmt->error);
die("Database error, contact site administrator");
if ($stmt->store_result() === false)
error_log($stmt->error);
die("Database error, contact site administrator");
如果有零行,则表示用户名不匹配任何内容。您想在错误日志中了解这一点,但不要将其透露给用户。他们应该只知道用户名或密码错误,而不是哪个错误。
if ($stmt->num_rows == 0)
error_log("Username '$username' not found");
die("Incorrect username or password");
if ($stmt->bind_result($id, $user, $pass) === false)
error_log($stmt->error);
die("Database error, contact site administrator");
应该只有一行与用户名匹配。因此,如果它没有匹配的密码,请随意 die()。
while ($stmt->fetch())
if (password_verify($password, $pass) === false)
error_log("Username '$username' found, but password is wrong");
die("Incorrect username or password");
$stmt->close();
最后,最后一步:如果我们走到了这一步,那么它一定是成功的。如果你在每个错误条件下都更早地 die(),那么你就不必担心深度嵌套的代码块。
echo "<p>Welcome! You are logged in, $username</p>";
【讨论】:
我到达store_result()
时遇到了错误。错误日志说:[10-Feb-2020 05:19:00 UTC] Commands out of sync; you can't run this command now [10-Feb-2020 05:19:05 UTC] PHP Notice: session_start(): A session had already been started - ignoring in /home/xk6wgsxybs5t/public_html/CookingForAlaska/includes/dblogin.php on line 7
啊哈——你必须已经在这个 PHP 请求中运行了另一个 SQL 查询,并且它仍在进行中。有关“命令不同步”错误的解释,请参阅我对 ***.com/a/3632320/20860 的回答。
好的。所以我将$sql
更改为$sql2
,因为我确实看到我有另一个请求并认为可以解决它。但是,我仍然收到错误[11-Feb-2020 22:30:06 UTC] Commands out of sync; you can't run this command now [11-Feb-2020 22:30:19 UTC] Commands out of sync; you can't run this command now
。我还尝试完全从页面中删除整个其他 SQL 查询,但仍然得到相同的错误。我更新了我的原始帖子以显示页面中的整个编码,包括其他 SQL 查询。
您连续两次致电store_result()
。这是导致错误的原因吗?
我想我没有看到我在哪里调用它两次,除非 if
语句是什么再次调用它?以上是关于登录页面的准备语句问题的主要内容,如果未能解决你的问题,请参考以下文章