首页 > 解决方案 > 登录页面的准备语句问题

问题描述

我正在尝试为我的网站创建一个登录页面。我从我建立的另一个网站复制并粘贴了这个,登录工作正常。我使用 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>

标签: phpmysqlauthenticationmysqliprepared-statement

解决方案


我测试了你的代码,它可以工作。没有什么问题。

我建议尽管您说您仔细检查了数据库,但问题是此 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>";

推荐阅读