代码之家  ›  专栏  ›  技术社区  ›  Jananath Banuka

如何检查用户名和密码是否与数据库值匹配

  •  4
  • Jananath Banuka  · 技术社区  · 7 年前

    如果这个问题看起来很愚蠢,我真的很抱歉。但几天来我一直在检查我的 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");
        }
        ?>
    

    所以忽略这一部分。

    3 回复  |  直到 4 年前
        1
  •  16
  •   O. Jones    4 年前

    被网络罪犯破解。

    人们对糟糕的安全代码没有多少幽默感。你会对像你这样的代码产生强烈反应,因为Equifax、Ashley Madison和Adobe,以及所有其他被网络罪犯破解的地方。为什么我们跳到你身上?因为我们不喜欢网络罪犯,也不想让他们过得轻松。朋友不要让朋友做不好的密码安全。朋友不会向朋友显示非常不安全的密码验证代码。

    你的代码怎么了?您将密码存储为纯文本,很容易受到SQL注入的攻击。我将讨论其中的第一个问题。

    幸运的是,php拥有出色的业界领先的密码安全设施。请在此处阅读。 http://php.net/manual/en/faq.passwords.php 使用它们。你如何处理密码?

    1. 当用户在您的站点上注册并首次提供密码时,您可以将其散列在服务器上运行的代码中,类似这样。
      $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
    
    1. 当用户尝试登录时,您可以在服务器上执行以下查询:

       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 */
     }
    

    这个序列是经得起未来考验的,因为如果旧的哈希方法太容易被网络爬虫破解,它可以在以后重新刷新密码。许多用户帐户的生命周期远长于php等软件包版本。

    要使密码等凭据保持机密,您需要 必须 使用https而不是http在浏览器和服务器之间进行连接。否则,网络罪犯可以拦截从用户到服务器的流量,并获取她的密码。装配一个支持https的服务器可能是一个棘手的问题,但这是部署web应用程序的关键部分。(像Heroku这样的服务可以让你轻松地用https测试你的应用。)

        2
  •  3
  •   Dharman Aman Gojariya    4 年前

    上面的评论提到了一些问题。

    混合mysql_*与mysqli_*API

    使用调用查询 mysqli_query() mysql_fetch_assoc() . 您不能混合使用这些不同的API。这个 mysql_* 函数不会使用您打开的连接 mysqli_connect() ,反之亦然。选择一个MySQL扩展并坚持使用它。

    mysql_* 完全它已被弃用,并已从PHP 7.0中删除+

    使用条件查询 二者都 用户名和密码

    只需搜索用户名,然后获取密码。如果您搜索 ,则搜索将返回零行,除非使用了正确的密码。

    你不会想要的。您希望避免将明文密码放入SQL查询中。只需搜索用户名,获取存储的密码,然后将获取的内容与用户输入的密码进行比较。

    如果从查询中获取零行,则 $check_username $check_password 从未设置。然后比较if语句中的这些变量。不是致命的错误,但风格不好。

    无密码哈希

    您似乎在将用户输入(我假设是纯文本)直接与数据库中存储的内容进行比较。 You're Probably Storing Passwords Incorrectly.

    相反,当您存储密码时,请使用 password_hash() 第一

    没有查询参数

    我知道你说过你不在乎你的SQL注入漏洞,但这就像是一个电工说你不在乎你的配电盘塞满了油布。一定要在你的LinkedIn个人资料上贴出你对安全的漠视,这样雇主就知道该避开谁了。

    建议的实施

    mysqli_report(MYSQLI_REPORT_ERROR | 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");
    
        3
  •  1
  •   rickdenhaan    7 年前

    这里有几个问题,无论是在您的代码中还是在思考过程中。让我们继续往下走:

    $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() 相反(打开 而不是 $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> $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>";
    }
    

    一旦你修复 全部的 在这些问题中,你还有一些想法要做。

    • 你应该 从不 在数据库中以明文形式存储密码。
    • 您现在可能不关心SQL注入,但通过您当前的查询,我可以作为任何有效用户(例如“admin”)登录,方法是将他们的用户名键入 admin' AND 1 -- ,或者如果我只想访问,我可以使用的用户名 any' OR 1 -- 并作为表中的第一个用户登录。查看准备好的报表及其工作方式。

    这里的主要教训应该是:当你在开发时,它不起作用,总是检查错误日志,看看它是否包含任何提示,并打开PHP的错误报告功能,这样你就可以看到你在浏览器中做错了什么。