首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何检查用户名和密码是否与数据库值匹配

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

Stack Overflow用户
提问于 2017-10-18 21:43:27
回答 3查看 67.9K关注 0票数 5

如果这个问题看起来很傻,我真的很抱歉。但是几天来,我一直试图检查数据库中的usernamepassword是否与我在html页面中输入的内容相匹配.这是我的登录表格..。

代码语言:javascript
运行
复制
<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>

这是我在Dashboard.php中使用的代码(Dashboard.php)

代码语言:javascript
运行
复制
<?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注入是开放的,但我并不关心它,因为这是我需要向我的朋友展示的一个示例,因此忽略了这个部分。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-10-18 22:32:08

堆栈溢出是为“专业和热心的程序员。”恕我直言,您已经在您的问题中向我们展示了代码,这些代码甚至不配使用任何一个名称。这是非常不安全的,如果你把它放在公共互联网上,你的网站将被网络罪犯破解。

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

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

幸运的是,php有出色的业界领先的设施来做密码安全.在这里读到他们的故事。http://php.net/manual/en/faq.passwords.php使用它们。你如何处理密码?

  1. 当用户在您的站点上注册并首次显示密码时,您可以在运行在服务器上的代码中散列它,如下所示。
代码语言:javascript
运行
复制
  $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. 当用户尝试登录时,您在服务器上执行如下查询: 从log_password选择log_user,其中log_username = TheUsernameGiven 然后将检索到的密码放入名为$hash的变量中。 然后,再次在服务器上使用函数来检查您的潜在用户刚刚提供的密码是否与数据库中的密码匹配。 最后,在您的服务器上,您检查用户的密码是否需要重新哈希,因为以前用于散列的方法已经过时了。
代码语言:javascript
运行
复制
 $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的服务器可能会让xxx头疼,但它是部署web应用程序的关键部分。(像Heroku这样的服务可以让您轻松地用https测试应用程序。)

票数 19
EN

Stack Overflow用户

发布于 2017-10-18 22:31:06

有几个问题,上面的评论中提到了一些问题。

混合mysql_*与mysqli_* API

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

提示:根本不要使用mysql_*。它被弃用,并已从PHP中删除。

查询用户名和密码的条件

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

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

未初始化变量

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

无密码散列

您似乎在将用户输入(我假设是纯文本)与存储在数据库中的内容直接进行比较。你可能把密码放错了。

相反,当您存储密码时,请首先使用散列()

没有查询参数

我知道你说过你不在乎你的SQL注入漏洞,但这就像一个电工,你说你不在乎你的电子面板里塞满了油性的破布。一定要在你的LinkedIn个人资料上发布你对安全的漠视,这样雇主就知道该避免谁了。

建议的执行

代码语言:javascript
运行
复制
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
EN

Stack Overflow用户

发布于 2017-10-18 22:22:14

这里有几个问题,无论是在代码中还是在思想过程中。让我们继续努力吧:

代码语言:javascript
运行
复制
$un = $_POST['username'];
$pw = $_POST['password'];
print $pass . "_" . $email;

那条print线应该给你一个警告。变量$pass$email不存在。您应该删除这一行,除非您尝试的是打印$un$pw

代码语言:javascript
运行
复制
$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对象。

代码语言:javascript
运行
复制
$result_can = mysqli_query($conn, $query);

这一行需要移除。您已经执行了查询,$query是它的结果,您在这里所做的没有意义,应该给您一个警告,甚至是致命的错误。

代码语言:javascript
运行
复制
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上):

由于您只对是否有任何结果感兴趣,所以整个部分可以更改为:

代码语言:javascript
运行
复制
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变量非常无用,您最好直接将消息放入警报中:

代码语言:javascript
运行
复制
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的错误报告功能,这样您就可以在浏览器中看到您做错了什么。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46819734

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档