简体   繁体   English

Mysqli:我无法使用散列密码登录

[英]Mysqli: I can't login with hashed password

I'm using mysqli with hashpassword.我正在使用带有 hashpassword 的 mysqli。 I can't log in using my password and I don't know why.我无法使用我的密码登录,我不知道为什么。 I tried all my best but its not working at all.我尽了最大的努力,但它根本不起作用。

I'm using utf8 in my database.我在我的数据库中使用 utf8。

This is my regiter php这是我的注册 php

<?php
if(isset($_POST["register"])){

    if(!empty($_POST['name']) && 
       !empty($_POST['studno']) &&
       !empty($_POST['password']) && 
       !empty($_POST['cpassword']) && 
       !empty($_POST['email'])) 
    {
        $name=$_POST['name'];
        $studno=$_POST['studno'];
        $password= password_hash($_POST['password'],PASSWORD_BCRYPT);
        $email=$_POST['email'];

        $con=mysqli_connect('localhost','root','') or die(mysqli_error($con));
        mysqli_select_db($con,'inventory') or die("cannot select DB");

        $query=mysqli_query($con,"SELECT * FROM users WHERE studno='".$studno."'");
        $numrows=mysqli_num_rows($query);
        if($numrows==0) {
            $sql = "INSERT INTO users(name,studno,email,password) "
                 . " VALUES('$name','$studno','$email','$password')";

            $result=mysqli_query($con,$sql);
            if ($_POST['password'] == $_POST['cpassword']) {
              if ($result) {
                  header("Location: index.php?registered=1");
              }
            } else {
               header("Location: signup.php?passwordnotmatch=1");
            }
        } else { /* numrows != 0 */
            header("Location: signup.php?alreadyinuse=1");
        }

} else {
    header("Location: signup.php?allfieldisrequired=1");
    }
}
?>

this is my log in php.这是我的php登录。

<?php
if (isset($_POST["login"])) {
    if (!empty($_POST['studno']) && !empty($_POST['password'])) {
        $studno=$_POST['studno'];
        $password=$_POST['password'];
        $con=mysqli_connect('localhost','root','') or die(mysql_error($con));
        mysqli_select_db($con,'inventory') or die("cannot select DB");
        $query=mysqli_query($con,"SELECT * FROM users WHERE studno='".$studno."' AND password='".$password."'");
        $numrows=mysqli_num_rows($query);
        if ($numrows!=0) {
            while($row=mysqli_fetch_assoc($query)) {
                $dbstudno=$row['studno'];
                $dbpassword=$row['password'];
            }
            if ($studno == $dbstudno && password_verify($dbpassword,$row['password']))) {
                session_start();
                $_SESSION['sess_user']=$studno;
                /* Redirect browser */
                header("Location: home.php");
            }
        } else {
            header("Location: index.php?error=1");
        }
    } else {
        header("Location: index.php?missing=1");
    }
}

A lot of people commented this already, but I shall post it as an answer:已经有很多人对此发表了评论,但我将其作为答案发布:

There are quite some things wrong with your code:您的代码有很多问题:

1) You need to verify the user's input against the database, not the database against the database. 1)您需要针对数据库验证用户的输入,而不是针对数据库验证数据库。 What this means is that the following line will work:这意味着以下行将起作用:

password_verify($password,$row['password'])

2) Your SQL queries do not have anything to prevent sql injection, look it up. 2)你的SQL查询没有任何防止sql注入的东西,查一下。

3) Your registration page allows for user iteration, look it up. 3)您的注册页面允许用户迭代,查找。

4) Don't use a while loop to get only the first row of a database, just use a single mysqli_fetch_assoc and it will return the first row. 4)不要使用while循环只获取数据库的第一行,只需使用单个mysqli_fetch_assoc,它将返回第一行。 Also use LIMIT 1 at the end of your query if you expect only one result.如果您只希望得到一个结果,也可以在查询结束时使用 LIMIT 1。

5) When selecting from a database, always specify the columns you need returned unless you are absolutely sure you need ALL columns that are returned, this will speed up your queries a lot. 5)从数据库中选择时,请始终指定需要返回的列,除非您绝对确定需要返回的所有列,这将大大加快您的查询速度。

6) Create your mysqli connection globally (for instance, create a database.php file and connect to the database there) instead of creating a connection in every php file you use. 6) 全局创建您的 mysqli 连接(例如,创建一个 database.php 文件并在那里连接到数据库),而不是在您使用的每个 php 文件中创建一个连接。

7) Start the session globally (for instance, create a user.php file where a session is created and the currently logged in user data is stored). 7) 全局启动会话(例如,创建一个 user.php 文件,在其中创建会话并存储当前登录的用户数据)。 Your registration page should check for a logged in user and so does the login page (why login or register if already logged in?) so you need to globally start the session somewhere.您的注册页面应该检查登录用户,登录页面也是如此(如果已经登录,为什么要登录或注册?)所以您需要在某个地方全局启动会话。

You are verifying the same password with the same hash.您正在使用相同的哈希验证相同的密码。 Use

 password_verify($password, $dbpassowrd);

And your code is easily vulnerable to SQL Injection attacks.而且您的代码很容易受到 SQL 注入攻击。 Validate it, sanitize user input and use prepared staments.验证它,清理用户输入并使用准备好的语句。

What you need to do is simple.您需要做的很简单。 Your code will never return results for this one reason "SELECT * FROM users WHERE studno='".$studno."' AND password='".$password."'" this will never return any results, as you have saved the password as hash when registering, now what happens, when a user log's in you are selecting the everything from the users table that that matches the where clause which is the studno and a password so this will never work as the password that comes from the user is unhashed therefor it will never match a hashed password.由于"SELECT * FROM users WHERE studno='".$studno."' AND password='".$password."'"这一个原因,您的代码永远不会返回结果,因为您已保存注册时将密码作为哈希值,现在会发生什么,当用户登录时,您从用户表中选择与 where 子句匹配的所有内容,即studnopassword因此这永远不会用作来自用户的密码未经过哈希处理,因此它永远不会匹配经过哈希处理的密码。 You need to remove the password from the where clause, and only have the id in the where clause.您需要从 where 子句中删除密码,并且只有 where 子句中的 id。

Again this is wrong password_verify($dbpassword,$row['password'])) remember $dbpasssword and $row['password'] are the same thing remember you have this in your script $dbpassword=$row['password'];这又是错误的password_verify($dbpassword,$row['password']))记住 $dbpasssword 和$row['password']是一样的 记住你的脚本中有这个$dbpassword=$row['password']; so basically your password_verify() is reading like this password_verify(storedHash,storedHash) You are verifying a stored hash against the same stored hash.所以基本上你的password_verify() password_verify(storedHash,storedHash)像这样password_verify(storedHash,storedHash)你正在验证存储的哈希值与相同的存储哈希值。 password_verify() should always read like : password_virify(PasswordFromTheUserInput,StoredHash) you must verify the password from the user input against the stored hash. password_verify() 应该始终读作: password_virify(PasswordFromTheUserInput,StoredHash)您必须根据存储的哈希值验证来自用户输入的密码。

So with that been said your script should look similar to this:因此,话虽如此,您的脚本应该与此类似:

<?php
ob_start();
session_start();

//Extract the inputs from the user



$query  = ("SELECT  studno,password FROM users WHERE studno='" . $studno . "'");
$result = $con->query($query);
if ($result->num_rows > 0) {
    // we have the results
    while ($row = $result->fetch_assoc()) {

        $dbstudno   = $row['studno'];
        $dbpassword = $row['password'];

        // check user password against stored hash
        if (password_verify($password, $dbpassword)) {
            // password correct start a session

            $_SESSION['sess_user'] = $studno;
            /* Redirect browser */
            header("Location: home.php");
        } else {

            header("Location: index.php?error=1");

        }


    }
} else {
    header("Location: index.php?missing=1");
}
?>

Hope this helps, I might have missed something but the logic should be someway be identical to the above, I'm not good with mysqli, I use PDO most of my life.希望这会有所帮助,我可能错过了一些东西,但逻辑应该与上述相同,我不擅长 mysqli,我大部分时间都在使用 PDO。

NB: Please take into consideration the answer from @John Smith he made very important points that you need to apply.注意:请考虑@John Smith 的回答,他提出了您需要应用的非常重要的观点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM