【问题标题】:Does these PHP if statements have a logic error?这些 PHP if 语句有逻辑错误吗?
【发布时间】:2012-11-03 18:46:56
【问题描述】:

以下是单击表单的更改密码按钮时运行的脚本。该表单包含 2 个密码字段,一个用于新密码,一个用于确认新密码。下面是表单的动作脚本:

<?php
session_start();

include("func.php");

$NewPassword = mysql_real_escape_string(md5($_POST['newpassword']));
$Confirm = mysql_real_escape_string(md5($_POST['confirmnewpassword']));
$userid = $_SESSION['username'];

if (!isset($NewPassword) || !isset($Confirm)) {
    header("Location: ../error.php");
    die("Error");
}else if ($NewPassword <> $Confirm) {
    header("Location: ../error.php");
    die("Error");
}else{
    dbConnect();

    mysql_query("UPDATE users SET password='$Confirm' WHERE username='$userid'");

    mysql_close($connect);

    header("Location: ../profile.php");
    die("Success");
}
?>

即使表单上的 2 个密码字段为空或不匹配,密码仍会在数据库中更新。这可能是什么原因?

感谢您提供的任何帮助。

【问题讨论】:

  • isset() 将允许空密码通过,不仅因为它认为要设置空值,还因为md5()始终生成非空哈希。此外,由于您在输入中使用md5(),因此无需转义它。
  • 第二种情况更有趣,因为如果密码确实不同,它应该不符合这个条件($NewPassword &lt;&gt; $Confirm)。我建议删除重定向并执行var_dump($_POST) 并查看确切的内容。
  • 调试的第一步是var_dump...谢谢@NullUserException

标签: php mysql if-statement logic


【解决方案1】:

你不需要 mysql_real_escape_string 包含 md5 函数,因为 md5 返回一个十六进制数。

 if (!isset($NewPassword) || !isset($Confirm)) {

永远不会评估为真,您应该检查 $_POST['newpassword'] 和 $_POST['confirmnewpassword'] 是否不为空 - 在这种情况下,如果密码都为空,则密码将被更新。

关于即使密码不同也会更新密码,您是否 100% 确定您使用 POST 而不是 GET 传递变量,并且参数的名称是“newpassword”和“confirmnewpassword”?

尝试放置一个“回显”来显示变量的值,以确保您正确传递参数,99% 的问题都存在。

【讨论】:

  • $_POST['newpassword'] 上使用 isset 不会给你想要的结果:ablazex.com/demos/post.php
  • @NullUserException - 你觉得使用 !empty 而不是 isset 怎么样?
  • 谢谢!我需要做的就是将 !isset() 更改为 empty(),它工作得非常好。
【解决方案2】:

您的代码中没有任何内容可以防止空字符串被散列和上传。您正在检查哈希,而不是原始字符串。这可以解释为什么空值仍然得到更新。

但是,如果值不匹配,则它们的哈希值应该不同。这向我表明,您的变量 $_POST['newpassword']$_POST['confirmnewpassword'] 可能不准确。正如其他人所建议的那样,代码开头的var_dump 甚至print_r($_POST) 语句将帮助您诊断此问题。

甚至不涉及诸如 PDO 与 mysql 之类的宏观问题或以不同方式构建代码,这就是我要做的:

session_start();
include("func.php");

print_r ($_POST); // you'll want to delete this later 

$new_password = $_POST['newpassword']; // not technically necessary, my preferred style
$confirm_password = $_POST['confirmnewpassword']; // also not technically necessary
$userid = $_SESSION['username'];


/* Test the actual submitted password and confirmation to ensure they are set */
if (empty ($new_password) || empty ($confirm_password)) {
    /* header("Location: ../error.php"); */ // comment this out for now
    die ("Error: Password or Password Confirmation not set");
}

/* Test the actual submitted password and confirmation to ensure they match */
elseif ($new_password != $confirm_password) {
    /* header("Location: ../error.php"); */ // comment this out for now
    die("Error: Password and Password Confirmation do not match");
}

else {
    /* NOW that you have established the password and confirmation are both
     * set AND match, you get the hash value */
    $password_hash = mysql_real_escape_string(md5($new_password));
    dbConnect(); 
    mysql_query("UPDATE users SET password='$Confirm' WHERE username='$userid'");
    mysql_close($connect);
    /* header("Location: ../profile.php"); */ // comment this out for now
    die("Success: Updated");
}

这应该允许您调试您的脚本,看看出了什么问题。我的猜测是数据要么作为 GET 传递,要么变量名不正确。

接下来的步骤:

  1. 工作后,删除 var_dump 并取消注释您的重定向。
  2. 考虑重新编写 if 语句,以更明确地测试密码是否正确,如其他答案之一所述。
  3. 说真的,请查看PDOmysqli。程序 mysql_* 正在被贬低。
  4. 如果您不想走完整的 OOP 路线,请考虑创建 update_password () 和 send_error () 之类的函数。这将使您的代码更具可读性和可重用性。

但是一步一步,让我们调试这些当前的东西!

【讨论】:

    【解决方案3】:

    我找不到这不起作用的具体原因(尝试使用调试器或调试消息),但我肯定不会将我的密码更新放在“else”分支中!仅当您 100% 确定新密码及其确认匹配并且它们已根据您的密码策略进行验证时才更新密码。至少确保它们不是空字符串。

    【讨论】:

    • -1 这正是 OP 试图完成的任务。 (即:您没有提供任何有用的建议)
    • @NullUserException:我正在提供有用的建议。不要对你的反对票过于慷慨。 100% 确定两个值匹配与不是 100% 确定你抓住了所有其他可能的情况(防御性编程)
    • 您告诉 OP 确保密码匹配并且密码不为空,并且他/她正在尝试这样做。所以这根本不能回答问题。
    • @NullUserException:在我的编程课上(很久以前),我了解到您必须始终为意外情况做好准备。这就是应该使用“else”分支的目的。尤其是更改密码等重要操作。如果您学到了不同的东西,那很好,但是我。这不是拒绝我的回答的理由。如果您能撤消此操作,我将不胜感激。
    • 提供额外建议很好,但我对您的回答的问题是它没有回答问题。如果您解决 OP 的问题,我将删除反对票。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-17
    • 1970-01-01
    相关资源
    最近更新 更多