【问题标题】:What's the meaning of these two lines of PHP code?这两行PHP代码是什么意思?
【发布时间】:2019-10-14 04:39:07
【问题描述】:

如果用户在登录页面的密码和登录字段中键入正确的信息,我目前正在编写一个脚本来登录用户。该脚本运行良好,但我实际上并不知道这两行代码对整体用户体验的意义和作用。

我很快就要参加考试,我必须解释代码的含义,如果你们帮助我解释下面两行代码的作用,那将是绝对令人惊奇的。这是完整的脚本:

<?php  

require('db_connect.php');

if (isset($_POST['user_id']) and isset($_POST['user_pass'])) {

    $username = $_POST['user_id'];
    $password = $_POST['user_pass'];

    $query = "SELECT * FROM dataforlogin WHERE username='$username' and password='$password'";

    $result = mysqli_query($connection, $query) or die(mysqli_error($connection));
    $count = mysqli_num_rows($result);

    if ($count == 1) {

        header("location: ../staudal/dashboard/index.php");

    } else {

        echo "Fail";

  }
}

?>

我无法理解的两行代码是:

$result = mysqli_query($connection, $query) or die(mysqli_error($connection));
$count = mysqli_num_rows($result);

他们做什么以及为什么?

【问题讨论】:

  • 这看起来有点过时的代码(完整的SQL injection vulnerabilities) - 你可能想找到一个更现代的教程......
  • 第一个执行 MySQL 查询,第二个计算查询返回的行数。这些都在文档中,并且在任意数量的教程中都有解释。
  • @CD001 虽然它可能不是好的代码,但它并没有真正过时。它使用mysqli 而不是mysql。不幸的是,大多数程序员(包括教程编写者)都没有防范 SQL 注入。
  • @Barmar 我认为更现代的教程会使用绑定参数和password_hash(),并且不会在出错时回显“失败”。
  • @CD001 我不认为这是“旧”或“现代”的问题,它只是“坏”与“好”的区别。糟糕的代码不会过时。

标签: php mysql sql database mysqli


【解决方案1】:

这是一个很好的问题,因为根据现代安全和应用程序设计标准,这些行大多是错误的或无用的。我从来没有想过仅仅两行代码就有这么多错误。

应该是这样的

$stmt = $mysqli->prepare("SELECT * FROM dataforlogin WHERE username = ?");
$stmt->bind_param("s", $username);
$stmt->execute();
$result= $stmt->get_result()
$user = $result->fetch_assoc();

if ($user && password_verify($password, $user['password']))
{
    // write some info into the session
    header("location: ../staudal/dashboard/index.php");
    exit;
} else {
    echo "invalid";
}
  • 在第一行中,我们正在准备带有问号的 sql 查询,问号放置在变量应该去的位置(因此它被称为占位符)。
  • 在第二行中,我们将实际变量绑定到占位符,因此它将与查询分开发送到 mysql 服务器,它们将无法干预。
  • 然后实际执行查询。
  • 然后我们得到mysqli_result 变量,旧mysql 或新mysqli 查询的所有用户都熟悉-查询返回的实际数据源。
  • 然后我们正在尝试获取选定的行。
  • 那么我们同时检查两件事,
    • 我们的查询是否返回任何行
    • 如果是,从表单发送的密码是否与使用 password_verify() 函数存储在数据库中的密码相同
  • 其余部分与您的代码中的相同,除了两件事
    • 在重定向用户之前,您应该将一些关于他们的信息写入会话中,以便在其他页面上识别他们
    • 最好在发送 Location 标头后添加exit

希望这些解释对你的老师来说足够了

说真的,这个问题应该提高人们对 PHP 教育状况的认识。大多数在线和离线资源都在教授它,就好像它仍然是 PHP3 一样,只是对已弃用的功能进行了轻微的整容。但是这种在很多方面都是错误的方法仍然是一样的。

【讨论】:

  • 确实,您不应该在WHERE 子句中使用密码列过滤器,因为它可用于定时攻击,因为数据库旨在尽快返回数据,尤其是当密码列是 ( multicolumn) 索引,password_hash() 强制您使用password_verify(),您的密码受到time attacks 的全面保护。
  • 或者不使用or die(mysqli_error($connection)),您可能希望使用mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); 来实现抛出异常并在MySQL 相关代码周围使用try { ... } catch(Exception $e) {...} 块。
  • @raymond 你不应该默认捕获异常。
  • 品味和目标的问题我猜想,我认为你的意思是默认抛出异常,但很可能这确实是通过自定义类更好地处理,当连接失败时,你手动抛出 MySQLConnectException,因为我也相信现在我记得在某些 PHP 版本上还有一些奇怪的 mysqli_report() 错误。
【解决方案2】:

  • $result = mysqli_query($connection, $query) or die(mysqli_error($connection));
  • 这将执行 MySQL 查询,例如 SELECT * FROM <i>table</i> WHERE id = ?,然后保存结果。或者,如果查询失败,它会返回错误消息。

  • $count = mysqli_num_rows($result);
  • 这只是返回您的查询返回的行数。

    【讨论】:

      【解决方案3】:

      首先我想说,请使用准备好的语句。

      $result = mysqli_query($connection, $query) or die(mysqli_error($connection));
      

      mysqli_query() 函数对数据库执行查询,$connection 变量打开一个与您已在 db_connect.php 中创建的 MySQL 服务器的新连接,并检查连接是否已建立或不。如果没有,die() 函数将运行。它用于打印消息并退出当前的 php 脚本。

      $count = mysqli_num_rows($result);
      

      mysqli_num_rows() 函数将返回结果集中的行数,您将该数字存储到 $count 变量中。

      希望对你有帮助

      【讨论】:

        【解决方案4】:

        我是一名初级开发人员,但我希望这个答案对您的代码有所帮助:

        1. $result = mysqli_query($connection, $query) or die(mysqli_error($connection));

          • $result 是一个 php 变量

          • mysqli_query($connection, $query) 表示 mysqli_query 将使用 db_connect.php 中声明的数据库连接数据库来运行查询 [$query = "SELECT * FROM dataforlogin WHERE username='$username' 和密码='$password'";]

          • 或死(mysqli_error($connection));表示如果mysqli_query没有找到指定的数据库或表,在这种情况下(dataforlogin),它会显示你的db_connect.php中指定的连接错误

        2. $count = mysqli_num_rows($result);

          • $count 是一个 php 变量

          • mysqli_num_rows($result);意味着 $count 等于运行 mysqli_query($connection, $query) 时在 $result 的表 (dataforlogin) 中找到的行数。

        注意:请避免使用 --- 或 die(mysqli_error($connection) 行,因为它可能会阻止页面加载,没有必要。

        【讨论】:

        • "请避免使用 --- or die(mysqli_error($connection) 因为它可能会阻止页面加载,没有必要。" 如果代码下面取决于一个有效的 MySQL 连接..
        • 也许这是必要的,但我更喜欢将它包含在我的 db_connect 代码中并在主页中省略它,它仍然对我有用。 #JuniorDeveloper
        • 您可以查看我的答案以获得深入的解释。
        猜你喜欢
        • 2011-05-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-04
        相关资源
        最近更新 更多