【问题标题】:Php verify hashed password not working iin my function [duplicate]php验证散列密码在我的函数中不起作用[重复]
【发布时间】:2019-09-22 14:37:10
【问题描述】:

我正在尝试为我的网站创建一个 API,为此我创建了一个函数。但是该功能无法使用 POST 功能在 POSTMAN 中验证我的密码。我一生都无法理解我错在哪里。

数据库中的密码是使用php hash function放置的:

    $password =password_hash($pass, PASSWORD_DEFAULT);                      

public function userLogin($username, $password){
    $stmt = $this->con->prepare("SELECT password FROM farms WHERE farmname = ? ");
    $stmt->bind_param("s", $username);
    $stmt->execute();
    $row = $stmt->get_result()->fetch_assoc();
    $hash = $row['password'];
    if (password_verify($hash, $password)) {
        return $stmt->num_rows > 0; 
    }
}

登录.php 文件

require_once '../includes/DbOperations.php';
$response = array();

if($_SERVER['REQUEST_METHOD']=='POST'){
    if(isset($_POST['username']) and isset($_POST['password'])){

        $db = new DbOperations(); 

        if($db->userLogin($_POST['username'], ($_POST['password']))){
            $user = $db->getUserByUsername($_POST['username']);
            $response['error'] = false; 
            $response['username'] = $user['farmname'];
        }else{
            $response['error'] = true; 
            $response['message'] = "Invalid username or password";          
        }
    }else{
        $response['error'] = true; 
        $response['message'] = "Required fields are missing";
    }
}

echo json_encode($response);

我没有得到用户名,而是不断收到错误消息:

{"error":true,"message":"无效的用户名或密码"}

【问题讨论】:

  • 附注:PDO 中的绑定参数应该是这样的:$stmt->bindparam(1,$username); 如果您使用的是问号
  • 没有@K.P.它不应该。 OP的做法是正确的
  • 尝试打印$hash并检查它是否返回正确的值。
  • 你的注册功能是如何工作的
  • 下面还有一些关于在你的登录中有一个 else 块的讨论,这不会解决你在这种情况下的错误,但目前如果 password_verify 失败,你的函数根本不会返回任何东西,因此,无论哪种方式,您都可能确实想要某种响应。我可能只是说 return password_verify(.... 然后你总是会从你的函数中得到一些反馈。

标签: php function mysqli postman


【解决方案1】:

交换参数:

if (password_verify($password,$hash)) {

【讨论】:

  • 然而,将参数包含在 password_verify 中是正确的方法,因此问题很可能出在其他地方
  • "数据库中的密码是使用php哈希函数放置的。"显示这是如何完成的!
  • @LarsStegelitz,我已编辑代码以添加该功能
【解决方案2】:

我认为userLogin 函数应该返回一个值( true/false ),而不管密码是否匹配,以便 if / else 逻辑起作用。因为password_verify 的返回值要么是真要么是假,你可以简单地返回。

public function userLogin($username, $password){
    $sql='select `password` from `farms` where `farmname` = ?'
    $stmt=$this->con->prepare( $sql );

    if( !$stmt )return false;
    $stmt->bind_param( 's', $username );

    $res=$stmt->execute();
    if( !$res )return false;

    $stmt->store_result();
    $stmt->bind_result( $pwd );
    $stmt->fetch();
    $stmt->free_result();
    $stmt->close();

    return password_verify( $password, $pwd );
}

--

在车库里很忙,但很快就根据我数据库中的数据整理了一个上述功能的小演示。

<?php
    if( $_SERVER['REQUEST_METHOD']=='POST' ){


        $dbhost =   'localhost';
        $dbuser =   'root'; 
        $dbpwd  =   'xxx'; 
        $dbname =   'experiments';
        $db     =   new mysqli( $dbhost, $dbuser, $dbpwd, $dbname );

        /* 
            the class from which userLogin originates was unknown so I guessed
            and made an ultra basic representation of what it might be.
        */
        class user{
            private $con;

            public function __construct( $con ){
                $this->con=$con;
            }

            public function userLogin($username, $password){
                $sql='select `password` from `farms` where `farmname` = ?';

                /*
                    as I do not have a table `farms` I chose another
                    table that has a hashed password column to test against.
                */
                $sql='select `hashpwd` from `users` where `username`=?';
                $stmt=$this->con->prepare( $sql );

                if( !$stmt )return false;
                $stmt->bind_param( 's', $username );

                $res=$stmt->execute();
                if( !$res )return false;

                $stmt->store_result();
                $stmt->bind_result( $pwd );
                $stmt->fetch();
                $stmt->free_result();
                $stmt->close();

                return password_verify( $password, $pwd );
            }       
        }//end class


        /* instantiate the class with the db as an argument */
        $user=new user( $db );

        /* capture POST vars */
        $username=filter_input( INPUT_POST,'username',FILTER_SANITIZE_STRING );
        $password=filter_input( INPUT_POST,'password',FILTER_SANITIZE_STRING );

        /* test if the password was OK or not... */
        if( $user->userLogin($username,$password) ){
            echo "OK";
        } else {
            echo "Bogus";
        }
        exit();
    }
?>
<!DOCTYPE html>
<html lang='en'>
    <head>
        <meta charset='utf-8' />
        <title>Farm - Form - mySQLi</title>
    </head>
    <body>
        <form method='post'>
            <input type='text' name='username' />
            <input type='password' name='password' />
            <input type='submit' />
        </form>
    </body>
</html>

不出所料,"OK" 表示该功能按预期工作。所以,总而言之,我认为问题出在其他地方

【讨论】:

  • 我尝试用我的代码替换您的代码,但仍然遇到同样的错误。 @RamRaider
【解决方案3】:

我认为你的函数在 if 之后需要一个 else 语句

例如:

if (password_verify($hash, $password)) {
        return $stmt->num_rows > 0; 
    }
else{}

【讨论】:

  • 虽然该方法最后可以使用return,但不确定为什么else 可以解决问题。
  • 拥有一个什么都不做的else 与根本没有else 没有什么不同。
  • @Rachel 是的,不,这不能成为解决方案,并且将其标记为对未来的访问者正确是不好的。
  • @prasinus,它不能解决问题。事实上,它甚至允许错误的密码登录
  • 那么我相信你应该尝试只返回 passwor_verify 函数而不是函数中的 num_rows 因为它也会返回 0 或 1。另外,交换 $hash 和 $password
猜你喜欢
  • 2020-08-16
  • 2015-06-08
  • 1970-01-01
  • 2020-03-09
  • 2019-05-26
  • 2016-05-22
  • 1970-01-01
  • 2014-12-03
  • 1970-01-01
相关资源
最近更新 更多