PHP - 字符串比较不起作用

时间:2014-03-30 08:37:42

标签: php mysql string-comparison

我正在为网站设置一个登录信息(也许我这样做的方式是错误的,但这是另一个问题)。

我这样做的方式是这样的:

  1. 在登录页面上从用户处获取用户名/密码。
  2. 使用帖子将这些传递给我的PHP。
  3. 在php中,收集从帖子传递的值。
  4. 比较从post传递给PHP的密码,以及从MySQL数据库中获取的密码。
  5. 我可以让数据库连接。我可以从数据库中提取密码。我可以从帖子中收集价值。但我无法比较这两个值 - 它总是说它们不相等,即使它们回应它们也是如此。

    收集我使用的已发布值:

    $posted_username = $_POST['uname'];
    $posted_password = $_POST['passwd'];
    

    要查询我使用的数据库:

    $result = mysql_query("SELECT passwd FROM usrs where usrname = '".$posted_username."'");
    

    接下来,如果我包含这一行:

    echo "Posted Username: " . $posted_username . "<br>" . " Posted Password: " . $posted_password . "<br>";
    

    我可以看到我的发布值已正确分配。我在运行PHP时得到了这个输出:

      

    发布用户名:admin   发布密码:admin2

    要逐步浏览我的数据库,请使用:

    while ($row = mysql_fetch_array($result, MYSQL_ASSOC))
    

    在这个while循环中,我去了:

    $password_fromdb = $row['passwd'];
    echo "Password from db is: " . $password_fromdb . "<br>";
    echo "Password from POST is: " . $posted_password . "<br>";
    $equal = strcmp($password_fromdb,$posted_password);
    

    两条回波线的输出给了我:

      

    db的密码是:admin2   POST的密码是:admin2

    所以我可以看到两个密码匹配。

    但是,无论我使用strcmp,还是使用=,==或====,我总是被告知我的两个密码不匹配。我被告知即使他们这样做也不会匹配!

    我做错了什么?我很感激帮助,因为我对PHP一无所知,必须为一堂课做这件事,我们的tutuor已经决定他不会教我们PHP。

3 个答案:

答案 0 :(得分:3)

您的代码中存在一些(我会说非常重要)问题,但您的实际问题看起来很简单。

由于您没有包含检查位置的代码,因此我将使用if ($equal) { execute your code }之类的内容来构建:

strcmp返回 0 表示相等。 &gt;如果string1大于string2则为1,如果string2大于string1则为&lt; 0

See the PHP docs for reference


如果你对自己的发展不感兴趣,你可以停止阅读,但我想我也可以解释一下你可以学到的一些东西:

尽管如此,我想提出一些问题,即使这从未使生产水平提高。这是一种明智的体验。

首先,让我强调一下,我要解释的是困难的,而且很少有人能够做到这一点 - 我自己可能也不是这项技能最熟练的人。 PHP的更高版本虽然为我们提供了这个功能。但我会给你一般的要点。

在所有情况下,您都希望哈希您的密码。散列是对文本的单向转换,不具备人类可读性。因为人类无法读取它,如果您的数据库遭到入侵,密码并非对入侵者公开可见,并且他将更难以从中获取任何数据。

还有一个名为 salting 的密码,salting只是说我们将自己的字符串添加到密码中,所以它永远不会完全是他们的密码。有几种方法可以做到这一点,但我不会详细介绍,因为 php提供了一个库来为我们做这件事。这意味着我们根本不需要做任何困难,只能使用他们的方法。 password_hash()password_verify() - 仅从PHP 5.5开始,但有backports to php 5.3.7

你必须自己从PHP官方网站查找这些方法,因为我只限发布两个链接。它们位于php.net/password_verify和php.net/password_hash


还有另一个问题,你正在使用MySQL,mysql已经过时了,甚至已经弃用了,建议你转到mysqli甚至pdo

安全问题2: 您的代码($result = mysql_query("SELECT passwd FROM usrs where usrname = '".$posted_username."'");)容易受到 MySQL注入的攻击。<​​/ p>

MySQL注入是有人试图切断你的查询,并使用他自己的。因为您没有正确地清理用户输入(从不信任用户),您实际执行的代码不是您所期望的那样,甚至可能包含多个查询(例如,可能会丢弃您的表,甚至尝试查找其中一些明文密码)。

PDO 为我们提供了这个,如果您正确使用PDO包装器(位于php.net/pdo),您根本不必担心这一点。 (嗯,你这样做,但是在你掌握它之后立即做到这一点要容易得多。)

还有MySQLi,它只是改进了MySQL_ *。它允许OOP编程并且更快。它不会为您清理用户输入,您必须使用mysqli_real_escape_string($str)$mysqli->real_escape_string($str),或者如果您坚持使用MySQL_ *函数,mysql_real_escape_string($str)


我现在暂时停止,这是一个很难处理的信息。但我希望有人从中学到一些东西。如果没有,那真的是一种耻辱。因为你真的使用了一些非常不安全的方法。鉴于您可以在本地进行测试,学习良好实践仍然是一件好事。

天儿真好!

答案 1 :(得分:1)

这可能取决于你如何使用$ equal。

如果strcmp相等(https://secure.php.net/manual/en/function.strcmp.php

,则返回0

所以如果你使用if($ equal)它会失败(因为等于0)

尝试使用var_dump($ equal)查看结果,然后尝试:

var_dump($equal);
if ( $equal === 0 ) {
    echo "It works!";
}

答案 2 :(得分:1)

在比较密码时遇到了同样(或类似)的问题。 strcmp()告诉我两个字符串不匹配,==告诉我他们不匹配......他们肯定匹配。

我的问题是mcrypt_decrypt()返回了一个32个字符的字符串,无论字符串实际上是多长时间。 Tre bizarre。

示例var_dump()输出为:

var_dump($password_entered,$password_decrypted_from_database);
string(11) "ThisIsATest"
string(32) "ThisIsATest"

解密后的一个简单trim()解决了这个问题。