【问题标题】:Fetch only one field in php and mysqli在 php 和 mysqli 中只获取一个字段
【发布时间】:2017-08-28 11:50:56
【问题描述】:

我有以下代码

if (isset($_POST['change'])) {
    $current = mysqli_real_escape_string($con, $_POST['current']);
    $password = mysqli_real_escape_string($con, $_POST['password']);
    $cpassword = mysqli_real_escape_string($con, $_POST['cpassword']);

    if(strlen($password) < 6) {
        $error = true;
        $password_error = "Password must be minimum of 6 characters";
    }
    if($password != $cpassword) {
        $error = true;
        $cpassword_error = "Password and Confirm Password doesn't match";
    }

    if(mysqli_fetch_field(mysqli_query($con, "SELECT password FROM users WHERE id = '" . $_SESSION['usr_id'] . "' LIMIT 1")) != md5($current)) {
        $error = true;
        $confirm_error = "Your actual password is not correct";
    }
}

问题出在这里:

mysqli_fetch_field(mysqli_query($con, "SELECT password FROM users WHERE id = '" . $_SESSION['usr_id'] . "' LIMIT 1"))

它给了我错误

PHP 可捕获的致命错误:第 27 行 /.../password.php 中的 stdClass 类的对象无法转换为字符串

我试过了

mysql_result(mysqli_query($con, "SELECT password FROM users WHERE id = '" . $_SESSION['usr_id'] . "' LIMIT 1"), 0)

但它不起作用,它给了我

PHP 致命错误:未捕获的错误:调用 /.../password.php:27 中未定义的函数 mysql_result()

我不想使用mysqli_fetch_array()while 循环。我搜索了一个函数或类似的东西,我找到了一些东西,但对我没有用。

【问题讨论】:

  • mysqli_real_escape_string($con, $_POST['password']) 你知道那会适得其反。
  • 可能与mysqli_fetch_field无关。转储$_SESSION['usr_id'],并将您的 mysqli_query 和 mysqli_fetch_field 语句分开。当然 mysql_result 不会起作用,它不是 mysqli 函数。
  • I don't want to use mysqli_fetch_array() and a while loop. .... 为什么?
  • 您的代码使用不安全;尤其是您使用的密码功能md5($current)。请勿不要将此放在网上。我称这是您的代码失败的“因祸得福”。
  • 确保在散列之前don't escape passwords或对它们使用任何其他清理机制。这样做会更改密码并导致不必要的额外编码。

标签: php mysql database mysqli


【解决方案1】:

我不认为这对您来说是最好的解决方案,但根据您的要求,您可能想要使用 mysqli_fetch_assoc。

$result = mysqli_query($con, "SELECT password FROM users WHERE id = '" . $_SESSION['usr_id'] . "' LIMIT 1");
$row = mysqli_fetch_assoc($result);

 if( $row['password']!= md5($current)) {
        $error = true;
        $confirm_error = "Your actual password is not correct";
 }

在下面的 cmets 中提到您应该使用参数化查询。对于用户密码,请使用密码哈希库,如 http://www.openwall.com/phpass/ 或 PHP 5 >= 5.5.0、PHP 7 中内置的 password_hash 函数。

要参数化当前查询并避免可能的 sql 注入攻击,请尝试以下代码。

$mysqliConnection = new mysqli("localhost", "my_user", "my_password", "my_dbname");

/* check connection */
if ($mysqliConnection->connect_errno) {
    echo "Failed to connect to MySQL: (" . $mysqliConnection->connect_errno . ") " . $mysqliConnection->connect_error;
}

$sql = "SELECT password FROM users WHERE id = ? LIMIT 1";
$stmt = $mysqliConnection->prepare($sql);
$stmt->bind_param("i", $_SESSION['usr_id']);
$stmt->execute();
$stmt->bind_result($password);
$stmt->store_result();
$row = $stmt->fetch()

现在您可以使用 $password 变量来检查您使用的密码散列。我希望这有帮助。

【讨论】:

  • 看来我误解了这个问题,并且毫无理由地被否决了。您愿意解释一下原因以便我改进吗?
  • 你真的不应该使用MD5 password hashes,你真的应该使用PHP的built-in functions来处理密码安全。在散列之前,请确保您 don't escape passwords 或对它们使用任何其他清理机制。这样做会更改密码并导致不必要的额外编码。
  • 任何投反对票的人理由,他们可能不会选择发表评论。在 Meta 上已经讨论了 cmets + downvotes 的问题。许多人只是选择DV并继续前进。许多人提供建议。许多人试图为新手照亮道路。教别人继续使用过时的方法和不安全的做法现在更有可能让你投反对票,因为许多人已经变得非常了解教真正的最佳做法。
  • 嗨 @JayBlanchard 我明白你的意思,对我来说最好给 cmets 投反对票,这样答案就会得到改善。我非常专注于帮助操作人员获得他想要的东西。我应该提到它不是最好的答案并避免非标准编码。感谢您让我知道将更新我的答案。
【解决方案2】:

你需要阅读mysqli_fetch_field()的文档:

将结果集的一列定义作为对象返回。重复调用此函数以检索有关结果集中所有列的信息。

此函数不返回结果集中某一列中的 ,它返回有关该列的元数据。比如列名、表名、数据类型、最大长度等。

如果您捕获该字段并将其转储,您会看到:

$passhash = mysqli_fetch_field(mysqli_query($con, "SELECT password FROM users WHERE id = '" . $usr_id . "' LIMIT 1"));
print_r($passhash);

输出:

stdClass Object
(
    [name] => password
    [orgname] => password
    [table] => users
    [orgtable] => users
    [def] => 
    [db] => test
    [catalog] => def
    [max_length] => 32
    [length] => 65535    <-- I used TEXT for the password column 
    [charsetnr] => 8
    [flags] => 16
    [type] => 252
    [decimals] => 0
)

请注意,它是作为对象返回的,而不是标量值。所以你不能直接把它和你的md5($current) 比较。它甚至没有您正在寻找的价值。

以下是我将如何编写您尝试执行的代码:

$sql = "SELECT password FROM users WHERE id = ? LIMIT 1";
$stmt = mysqli_prepare($con, $sql);
$stmt->bind_param($stmt, "i", $_SESSION['usr_id']);
$stmt->execute();
$result = $stmt->get_result();
$match = false;
while ($row = $result->fetch_assoc()) {
    if ($row['password'] == md5($current) {
        $match = true;
    }
}
if (!$match) {
    $error = true;
    $confirm_error = "Your actual password is not correct";
}

你的另一个错误:

调用未定义函数mysql_result()

mysql_result() 函数已被弃用,并且在 PHP 7 中已被删除。无论如何它不能与 mysqli_query() 一起使用,因为它是不同 API 的一部分,并且这两个 API 不能混合使用。

mysqli_result(注意 mysqli,不是 mysql)是资源类的名称,而不是函数。

【讨论】:

    猜你喜欢
    • 2018-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-08
    • 1970-01-01
    • 1970-01-01
    • 2021-06-24
    • 2011-12-04
    相关资源
    最近更新 更多