PHP password_verify 即使硬编码也总是返回 false

PHP password_verify always returning false even when hardcoded

这是我的代码:

function login() {
    //Declare variables
    $username = $_POST["login"]; 
    $password = $_POST["password"];
    $client = $_POST["clients"];

    //QueryDB
    $servername = "localhost";
    $SQLUsername = "XXXX";
    $SQLPassword = "XXXX";
    $dbname = "XXXX";

    $conn = new mysqli($servername, $SQLUsername, $SQLPassword, $dbname);
    // Check connection
    if ($conn->connect_error) {
      die("Connection failed: " . $conn->connect_error);
    }

    //Set query then run it
    $sql = "SELECT * FROM Users WHERE Username ='$username'";
    $result = $conn->query($sql);
    $row = $result->fetch_array(MYSQLI_ASSOC);

    //Verify Password
     if ($result->num_rows === 1) {
        if (password_verify($password, $row['Password'])) {
            //Build XML request
            $XMLRequest = "<?xml version='1.0'?><Login><Client>".$client."</Client><LoginDetails><Username>".$username."</Username><Password>".$newhash."</Password></LoginDetails></Login>";

            //Build URL
            $ReplacedValues = array("NewType" => "login", "NewHash" => $XMLRequest);
            $NewString = strtr($GLOBALS["params"], $ReplacedValues);

            $NewUrl = $GLOBALS["link"].$NewString;

            //Post to Server
            header('Location: '.$NewUrl);
        }
        else {
            echo "Password is wrong"."<br>";
            echo $password."<br>";
            echo $row['Password'];
        }
    } else {
        echo "more then 1 row";
    }

    mysqli_close($conn);
}

我的问题是,即使我将我的密码变量和哈希变量硬编码为它们各自的值,if 条件 returns 还是 false。知道为什么吗?该页面在加载时执行,加载 else 条件以向我显示用户输入的密码和来自数据库的正确哈希值。我的数据库设置为 CHAR(255) 作为密码。

更新** 这是我在评论中讨论的 C#。这不是完整的代码,只是数据库的插入语句部分。我可以很好地插入 SQL 服务器数据库。

public static string WebsiteRegister(XmlDocument XMLBody)
        {
            //Get SQL connection string
            XmlNodeList XMLNodes = SQLConnectionMethods.EstablishSQLServerConnection("SQL");
            string ConnectionString = XMLNodes.Item(0).ChildNodes[0].InnerText;
            string UserName = XMLNodes.Item(0).ChildNodes[1].InnerText;
            string Password = XMLNodes.Item(0).ChildNodes[2].InnerText;

            //Open connnection
            SqlConnection cnn = new SqlConnection(ConnectionString);
            SQLConnectionMethods.OpenSQLServerConnection(cnn);

            try
            {
                string username = XMLBody.SelectSingleNode("register/registerdetails/username").InnerText;
                string pass = XMLBody.SelectSingleNode("register/registerdetails/password").InnerText;
                string fname = XMLBody.SelectSingleNode("register/registerdetails/firstname").InnerText;
                string lname = XMLBody.SelectSingleNode("register/registerdetails/lastname").InnerText;
                string email = XMLBody.SelectSingleNode("register/registerdetails/email").InnerText;
                string accountRef = XMLBody.SelectSingleNode("register/registerdetails/accountreference").InnerText;
                string client = XMLBody.SelectSingleNode("register/client").InnerText;

                //Build Query string
                string queryString = $"Insert into [dbo].[UserAccounts] (AccountReference, FirstName, LastName, Email, Username, Pass, Client) values ('{accountRef}', '{fname}', '{lname}', '{email}', '{username}', '{pass}', '{client}')";

                //Process request
                using (SqlCommand myCommand = new SqlCommand(queryString, cnn))
                {
                    string Result = (string)myCommand.ExecuteScalar();

我在这里的代码中找不到任何问题,但是由于散列和验证是一个取决于很多因素才能成功的过程,我想给你一些提示,以便你可以自己检查是否有任何问题潜在问题。

  1. 确保你不是escaping/sanityzing之前的密码 散列它。这样您就可以更改存储的密码。让

    $密码=$_POST['password'];

在您创建帐户和 当您在登录时检查密码是否匹配时。

  1. 确保将散列变量括在单引号 (') 而不是双引号 (") 中。使用双引号会使 PHP 将每个成对的字符与“$”一起读取为个别变量可能会导致您的代码中断,请改用单引号。

  2. 确保数据库中的密码字段(存储哈希 密码)最多可存储 255 个字符。从文档 建议将结果存储在可以 扩展超过 60 个字符(255 个字符是一个不错的选择)。如果字段较窄,哈希将被截断,你永远不会 有一场比赛。

  3. 当您在登录时通过用户名获取用户时,请确保用户名是唯一的 只要它是您的主键(在 table 定义)。在用户注册和登录时(在 php 级别)也检查一下是个好主意。

  4. 回显散列和输入 值并确保它们与插入的值匹配 如果数据库值不同,则在 password_hash() 期间生成 (散列),确保其列的类型是 varchar(256), 散列通常是 60 个字符长,但散列函数是 经常改进,以便将来可以扩展长度。

  5. 如果输入的值不同(用户密码),请确保 过滤不会破坏密码值。

  6. 还要检查另一个变量是否与您存储密码的变量同名。

  7. 如果password_verify($password, password_hash($password, PASSWORD_DEFAULT)) “有效”,那么问题是 $row['Password'] 不包含预期的内容 - 包括未正确生成。

  8. 如果它“不起作用”那么 另一条线导致观察到的行为。这两个 结果允许专注于改进的问题集。

  9. 尝试更改另一列匹配的密码并将其复制到您的密码列并将该密码输入 check.if 它有效然后您存储的密码有问题

  10. 尝试将此哈希复制到您的密码列

    $2y$10$uDnEpQpkh9RO5tWwOrHtneLAuYMRDstRaKGZFyHubObDR0789OMO6

这是 123456 使用 bycrypt 的散列密码。 select 这个密码,并在 select 从 sql 中输入这个密码后,尝试用 password_verify(123456,$yourhashedfromdatabase) 验证它,如果它有效,那么你的数据之后可能有一些操作被输入并进入数据库。它不会通过回显检查到达数据库的密码是否与您输入的密码完全相同。

更新: 更新代码后,我看到在输入密码时使用“通过”列,但在提取密码时使用“密码”栏。这可能是问题