【问题标题】:Why doesn't the if statement work within this loop? PHP为什么 if 语句在这个循环中不起作用? PHP
【发布时间】:2012-11-06 01:11:28
【问题描述】:

我有一个遍历从 SQL 查询返回的行的 while 循环。该行中特定列的值存储在数组中。然后遍历数组,并将每个元素与用户的输入进行比较。如果输入与数组元素匹配,则布尔值变为真。我正在尝试这样做,以便用户可以输入密码来访问特定页面。然而它只是行不通。我已经打印了数组中的所有值以及输入,所以我知道那里没有问题。但由于某种原因,if 语句不会比较它们。代码如下:

if (isset( $_POST['ok'])) {
  $password = $_POST['pass'];
  $matched = false;
  $pw = array();
  mysql_connect("localhost", "xxx", "xxx")or die("Error");
  mysql_select_db("details")or die("Error");
  $query="SELECT * FROM members";
  $result=mysql_query($query);
  while ($row = mysql_fetch_assoc($result) ){
    $pw[] = $row["pass"];
  }
  foreach($pw as $p){
    if(strcmp($p, $password) == 0){
      $matched = true;
    }
  }
  if ($matched==true) {
    //Membership page
  } else {
    //Error message
  }
} else {
  ....

【问题讨论】:

  • 尝试将循环更改为 foreach($pw as $p){ if($p == $password){ $matched = true;break; } }
  • 别忘了从不存储纯密码,对它们使用散列算法
  • 你有想过区分大小写的问题吗?
  • @ItayMoav 休息;没有区别
  • @HamZaDzCyber​​DeV - 这只是一个用于测试的基本版本,真正的会有一个哈希算法

标签: php mysql arrays loops


【解决方案1】:

将您的查询更改为这样的内容会更容易和更有效

$dbh = mysql_connect("localhost", "xxx", "xxx") or die("Error");
mysql_select_db("details", $dbh ) or die("Error");

$pass = mysql_real_escape_string( $_POST['pass'], $dbh );
$user = mysql_real_escape_string( $_POST['user'], $dbh );

$sqlQuery = <<< EOQ
    SELECT
        *
    FROM
        `members`
    WHERE
        `user` COLLATE utf8_bin = '{$user}' COLLATE utf8_bin
        AND
        `password` COLLATE utf8_bin = '{$pass}' COLLATE utf8_bin
EOQ;

$result = mysql_query( $sqlQuery );
if ( $result and ( mysql_num_rows( $result ) === 1 ) {
       echo "success";
       $userDetails = mysql_fetch_assoc( $result );
} else {
       echo "username or password wrong";
}

编辑:更新密码和用户名检查以区分大小写

Edit2:上面的 cmets 提醒不要存储明文密码。更改为散列密码

UPDATE members SET pass = SHA1( pass );

然后将您的支票更改为

... AND pass = SHA1( '{$pass}' )

【讨论】:

  • 我不这样做的原因是因为我需要将列值存储在一个数组中,因为它们稍后会再次使用
  • 如果您以后需要所有用户记录,请另外获取它们。特别是在这种情况下,保持干净、简单和分离不属于这里的东西(单独的身份验证和其他用户数据处理)
  • 我不明白为什么人们仍然使用带有转义功能的过时 mysql 模块而不是带有准备好的语句的 mysqli 模块或 PDO...
  • Mysqli 确实是更好的适配器。准备好的语句通常被误用于转义。仅转义是准备好的语句的积极副作用,但不是最初的想法。
【解决方案2】:

找到匹配项后需要休息一下,以便 $matched 等于 true。

if ( isset( $_POST['ok'] ) ) {

$password = $_POST['pass'];
$matched = false;
$pw = array();

mysql_connect("localhost", "xxx", "xxx")or die("Error");
mysql_select_db("details")or die("Error");
$query="SELECT * FROM members";
$result=mysql_query($query);

while ($row = mysql_fetch_assoc($result) ){
$pw[] = $row["pass"];
}

foreach($pw as $p){
  if(strcmp($p, $password) == 0){
  $matched = true;    // found match so break out and do the membership.
  break;
}
}

    if ($matched==true) {

      //Memebrship page

    } else {

      //Error message
    }

} else {

....

【讨论】:

  • 这将更快地执行脚本,但不会改变任何结果行为,因为他在第二个(不必要的)循环中没有 else { $matched = false }
  • 不幸的是,这没有任何作用
【解决方案3】:

建议:

1) 用 PDO 替换直接的 mysql 函数调用:(这不需要任何转义,因为 PDO 会处理所有事情)

$mysql_host = "localhost";
$mysql_user = "xxx";
$mysql_password = "xxx";
$mysql_database = "details";
$dbLink = new PDO("mysql:host=$mysql_host;dbname=$mysql_database;charset=utf8", $mysql_user, $mysql_password, array(PDO::ATTR_PERSISTENT => true));
$query = db()->prepare("select * from members WHERE pass = ? limit 1");
$query->execute(array($_POST['pass']));
$query->setFetchMode(PDO::FETCH_ASSOC);
$myMember = $query->fetch();
$query->closeCursor();

2) 如果您想坚持使用您的代码,您可以使用$pwd = mysql_real_escape_string($_POSt['pass']) 作为发布的密码,然后选择包含转义接收密码$pwd 的行。另外,不要忘记mysql_free_result($result);!!!

3) 对密码进行哈希处理,因此您不需要使用 mysql_real_escape_string。使用$pwHash = md5($_POST['pass'])$pwHash = sha1($_POST['pass']) 或任意组合。

4) 请对齐您的代码。对于回答您的问题(提供帮助)的人以及未来的维护(您或其他人;相信我,您会在 2-3 年内忘记该代码),这将使其更具可读性。

5) 你的代码应该可以工作,我不知道为什么它不工作。尝试为$pw 添加 var_dump 并在密码匹配时在屏幕上写一些东西。也许你交换了页面(有错误的成员)

【讨论】:

  • 我为 $pw 添加了 var_dump,我还为输入文本添加了 var_dump....从中我可以看到数组包含输入字符串。所以我知道有一个匹配,它似乎没有进行实际比较,然后将布尔值更改为 true
  • 连接数据库时使用什么字符编码?字符编码是否有可能改变比较?
  • 另外,尝试在for 循环内回显您与strcmp 比较的参数。看看你在哪里。您可以在 for 中添加一个 echo,您将 match 设置为 true 以说服自己代码运行良好
【解决方案4】:

为什么是 foreach 循环?你可以这样做:

if (isset( $_POST['ok'])) {
  $password = $_POST['pass'];
  $matched = false;
  $pw = array();
  mysql_connect("localhost", "xxx", "xxx")or die("Error");
  mysql_select_db("details")or die("Error");
  $query="SELECT * FROM members";
  $result=mysql_query($query);
  while ($row = mysql_fetch_assoc($result) ){
    $pw[] = $row["pass"];
  }
   $pw_tmp = flip_array($pw);

   if(isset($pw_tmp[$password])){
      //Membership page
   }else{
      //Error message
   }
}else{
  // something else ...
}

【讨论】:

    猜你喜欢
    • 2014-02-23
    • 2011-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多