【问题标题】:Simple if() not working as expected简单的 if() 没有按预期工作
【发布时间】:2012-06-15 19:39:57
【问题描述】:

我确信我只是忽略了一些东西,我花了几天的时间来解决这个问题,但似乎无法弄清楚。

在上一页登录后我得到用户名和密码,

$username = mysql_escape_string($_POST['adminusername']);
$password = mysql_escape_string($_POST['adminpassword']);

然后我去数据库里把用户名和密码从数据库里拉出来,

$sql = "SELECT username, password FROM `weaponsadmin`";
$rows = $db->query($sql); while ($record = $db->fetch_array($rows)) {

现在这是让我感到困惑的部分,如果我有以下内容,无论我使用什么用户名或密码,它都不允许我登录,

if ( ($record[username]==$username) && ($record[password]==$adminpassword) ){
   $_SESSION['loggedin'] = true;
   $_SESSION['username'] = $adminusername;
   header( "Location: admin.php" ) ;
}
else {
   header( "Location: index.php?login=error" ) ;
}

但是,如果我使用以下内容,如果用户名正确,它将允许我登录,但它允许我输入任何密码并且它可以工作,

$adminusername = $record[username]; 
$adminpassword = $record[password];

if ( ($adminusername==$username) && ($adminpassword==$adminpassword) ) {
   $_SESSION['loggedin'] = true;
   $_SESSION['username'] = $adminusername;
   header( "Location: admin.php" ) ;
}
else {
   header( "Location: index.php?login=error" ) ;
}

总而言之,由于某种原因,&& 部分似乎无法正常工作,如果有人可以帮助我编写代码并让我知道我的代码可以在哪里改进以提高安全性以及如何使其正常工作,谢谢

【问题讨论】:

  • 数组索引应该是整数或字符串,所以$record[username]应该是$record['username']。如果没有引号,PHP 会尝试查找 username/password 常量。文档:php.net/manual/en/language.types.array.php
  • $adminpassword==$adminpassword 总是正确的......
  • @Wrikken 是的,这就是问题所在,谢谢,我知道这很简单

标签: php mysql login login-control login-script


【解决方案1】:

$adminpassword==$adminpassword 有什么意义:

我认为应该是:

if ( ($adminusername==$username) && ($adminpassword==$password) ){

【讨论】:

  • 这也可以解释为什么第一个例子从来没有奏效,因为在那种情况下,$adminpassword 从未被设置
【解决方案2】:

$record[username] 应该是 $record["username"](等等)。索引是字符串或整数

【讨论】:

    【解决方案3】:

    你用错了数组。
    你期望:$record[username]; //retrieve contains of key "username"
    真正发生的事情:

        $record[username]; 
        /* 
             retrieves a key in the record array under the key which is a value of a
             constant named "username" (if it's defined) and an empty string with 
             E_WARNING if it's not. 
        */
    



    您需要对索引名称进行单引号或双引号,例如$records['username']。 但是,您可以在字符串中使用不带引号的数组索引(这些索引将按您的预期工作)-> $someString = "Blahblahblah, ergo $record[username] is a donkey.";

    【讨论】:

      【解决方案4】:

      您可以使用=== 代替==。阅读this
      这里不需要 strcmp()。

      【讨论】:

      • 用恒等运算符代替等式真的能解决他的问题吗?
      • 这个代码是问题所在:$adminpassword==$adminpassword,就像 mgraph 之前说的,这个:$adminusername = $record[username]; $adminpassword = $record[password];,但使用=== 更安全
      【解决方案5】:

      添加到迈克尔的回答中,您不应该使用 == 进行字符串比较的原因(希望这将帮助您在将来解决类似的困难)是当您在对象上调用简单的 == 时(例如字符串,或者实际上是除 int、double、float、char、long、short 或 boolean 之外的任何其他语言,在大多数语言中),您真正要比较的是每个对象在内存中的地址,即指针值。

      如果您想知道两个变量是否引用同一个对象,这很有用,但如果您想知道两个对象是否相同,则不是很有用。所以这是真的:

      $string_a = $some_string;
      $string_b = $some_string;
      $string_a == $string_b;
      

      但这不是:

      $string_a = getUserInput();  # user types in "hello"
      $string_b = getUserInput();  # user types in "hello"
      $string_a == $string_b;
      

      如果它将字符串文字存储在内存中独立于它们所附加的用户定义变量,这可能取决于您所使用的语言:

      $string_a = "hello";
      $string_b = "hello";
      $string_a = $string_b;
      

      因此,除非您要检查两个对象是否实际上是同一个对象,而不仅仅是相同,否则请使用我之前建议的函数来比较两者。这样的函数通常会下降到原始类型的级别,可以使用 == 进行比较,如果所有这些比较都进行,则返回 true。

      【讨论】:

      • 为什么我们不应该在 php 中使用== 进行字符串比较?
      【解决方案6】:

      不要使用== 进行字符串比较。而是使用strcmp()=== 来匹配字符串。

      【讨论】:

      • 为什么我们不应该使用==进行字符串比较?
      • 它不准确,容易破解。只需查看用户 cmets 所在操作员部分的 php 在线文档即可。详细解释了为什么它不安全。谷歌搜索 php 字符串比较也会产生许多警告,不要依赖 == 或 === 出于多种原因。使用 strcmp、preg_match 或任何其他可靠函数来比较更可靠的字符串,尤其是在涉及管理员密码和用户名时。
      • == 和 === 非常可靠。这些都不是真的,使用 preg_match 进行字符串比较确实是一个荒谬的想法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-29
      • 1970-01-01
      • 1970-01-01
      • 2017-06-18
      • 1970-01-01
      相关资源
      最近更新 更多