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

时间:2017-10-18 21:43:27

标签: php mysql passwords php-password-hash

如果这个问题看起来很傻,我真的很抱歉。但是我几天来一直试图检查数据库中的usernamepassword是否与我在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注入是开放的,但我并不关心它,因为这是我需要向朋友展示的一个例子所以忽略那部分。

3 个答案:

答案 0 :(得分:6)

Stack Overflow适用于“专业和发烧友程序员”。尊敬的是,你已经向我们展示了你的问题中的代码,这些代码甚至不值得任何一个名字。

StackOverflow人员对糟糕的安全代码没有太大的幽默感。你得到像你这样的代码的强烈反应,因为,Equifax,Ashley Madison和Adobe,以及被网络犯罪分子破解的所有其他地方。我们为什么要跳上你?因为我们不喜欢网络犯罪分子,我们不想让他们生活轻松。朋友不要让朋友做错密码安全。朋友不会向朋友展示严重不安全的密码验证码。

您的代码有什么问题?您将密码存储为纯文本,并且您很容易受到SQL注入攻击。我将解决第一个问题。

幸运的是,php具有良好的密码安全性。在这里阅读它们。 http://php.net/manual/en/faq.passwords.php使用它们。你如何处理密码?

  1. 当用户在您的网站上注册并首先提供密码时,您可以将其哈希,就像这样。
  2.   $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检查您的用户刚给您的密码是否与您数据库中的密码相匹配。

      最后,检查是否需要重新设置用户的密码,因为之前用于散列的方法已经过时了。

    2.  $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>";
}

一旦你解决了这些问题的所有,你仍然有一些想法。

  • 永远不会在数据库中以纯文本格式存储密码。
  • 您现在可能不关心SQL注入,但是对于您当前的查询,我可以通过键入其用户名admin' AND 1 --作为任何有效用户(例如“admin”)登录,或者如果我只想访问我可以使用any' OR 1 --的用户名,并以表格中的第一个用户身份登录。查看准备好的陈述及其工作原理。
  • 您根本没有错误处理。您应该添加检查以查看数据库连接是否已成功打开,查询是否正确执行,表单是否已发布以及用户名/密码字段已填写并考虑如何向用户显示有用的错误消息。

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

答案 2 :(得分:1)

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

混合mysql_ *与mysqli_ * API

您使用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");