简体   繁体   English

PHP-字符串比较无法正常工作

[英]PHP - String comparison is not working

I am setting up a login for a website (perhaps the way I am doing it is just wrong, but that's for another question). 我正在为网站设置登录名(也许我这样做的方式是错误的,但这是另一个问题)。

The way I am doing it is like this: 我这样做的方式是这样的:

  1. Get username/password from user on login page. 在登录页面上从用户获取用户名/密码。
  2. Pass these to my php using post. 使用post将这些传递给我的php。
  3. In the php, collect the values passed from post. 在php中,收集从post传递过来的值。
  4. Compare the password passed to PHP from post, with one taken from a MySQL database. 比较从post传递到PHP的密码和从MySQL数据库获取的密码。

I can get the database to connect. 我可以连接数据库。 I can extract the password from the database. 我可以从数据库中提取密码。 I can collect the value from post. 我可以从帖子中收集价值。 But I CANNOT compare these two values - it always says they are not equal, even though echoing them says they are. 但是我无法比较这两个值-总是说它们不相等,即使回显它们是相等的也是如此。

To collect the posted values I use: 要收集发布的值,我使用:

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

To query the DB I use: 查询数据库,我使用:

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

Next, if I include this line: 接下来,如果我加入这一行:

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

I can see that my posted values have been assigned correctly. 我可以看到我的发布值已正确分配。 I get this output when I run the PHP: 运行PHP时得到以下输出:

Posted Username: admin Posted Password: admin2 已发布用户名:admin已发布密码:admin2

To step through my DB I use: 要逐步浏览数据库,请使用:

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

And inside this while loop I go: 在这个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);

The output of the two echo lines gives me this: 两条回声线的输出给了我这个:

Password from db is: admin2 Password from POST is: admin2 来自db的密​​码是:admin2来自POST的密码是:admin2

So I can see that the two passwords DO match. 因此,我可以看到两个密码确实匹配。

However, whether I use strcmp, or whether I use =, == or ====, I ALWAYS get told that my two passwords do not match. 但是,无论我使用strcmp还是使用=,==或====,我总是被告知我的两个密码不匹配。 I get told they don't match even if they do! 我被告知即使他们匹配,他们也不匹配!

WHAT am I doing wrong? 我究竟做错了什么? I would appreciate help as I know nothing about PHP, have to do this for a class, and our tutuor has decided he's not going to TEACH us PHP. 我将不胜感激,因为我对PHP一无所知,所以必须为一堂课做这件事,而且我们的教师决定他不打算教我们PHP。

There's a few (I'd say pretty significant) issues with your code, but your actual issue is looking to be simple. 您的代码有一些(我会说很重要)问题,但是您的实际问题看起来很简单。

As you didn't include the code for where you check, I'm going to build off the fact you're using something like if ($equal) { execute your code } : 由于您没有包括要检查的代码,因此我将基于您使用if ($equal) { execute your code }这样的事实:

strcmp returns 0 for being equal. strcmp返回0等于。 >1 if string1 is greater than string2, and <0 if string2 is greater than string1 如果string1大于string2,则> 1;如果string2大于string1,则<0

See the PHP docs for reference 请参阅PHP文档以供参考


You can stop reading past this if you're not interested in developing yourself, but I figured I might as well explain a few things you could learn from: 如果您对自己的发展不感兴趣,可以停止阅读,但我认为我不妨解释一些您可以从中学到的东西:

That said however, there are a few issues I would like to raise awareness of, even if this never makes production level. 话虽这么说,但我想提高一些意识,即使这从来没有达到生产水平。 It's a wise experience. 这是一个明智的经验。

First of all, let me emphasise that what I am about to explain is difficult, and few people get it right - I myself am probably not the most proficient person on this skill either. 首先,让我强调一下,我要解释的内容很困难,很少有人理解正确-我本人也可能不是最熟练的人。 Later versions of PHP have this covered for us though. PHP的更高版本对此有所介绍。 But I'll give you the general gist. 但是,我将给您概括。

In all cases, you will want to hash your passwords. 在所有情况下,您都希望对密码进行哈希处理 Hashing is a one-way transformation of text that is not humanly readable. 散列是人类无法阅读的单向文本转换。 Because it is not readable by humans, if your database gets compromised, the passwords are not all publically visible to the intruder, and he will have a harder time getting any data out of it at all. 由于数据库无法被人类读取,因此如果入侵者入侵数据库,密码就不会对入侵者公开可见,这样,入侵者将很难从中获取任何数据。

There is also this thing called salting your passwords, salting is just a way of saying that we add our own string to their password, so it's never completely their password. 还有这个东西叫做腌制您的密码,腌制只是说我们自己的字符串添加到其密码的方式,所以它完全是从来没有自己的密码。 There's a few ways to do this, but I won't go into detail, because php offers a library that does this for us. 有几种方法可以做到这一点,但我不会详细介绍,因为php提供了一个为我们完成此任务的库 Which means we won't have to do anything difficult at all, and can just use their methods. 这意味着我们根本不需要做任何困难,只需使用它们的方法即可。 password_hash() and password_verify() - it is only since PHP 5.5, but there are backports to php 5.3.7 password_hash()password_verify() -仅从PHP 5.5开始,但是有向后移植到php 5.3.7

You'll have to look up the methods yourself from PHP's official website, as I'm limited to posting only two links. 您必须在PHP的官方网站上自行查找方法,因为我仅限于发布两个链接。 They're found at php.net/password_verify and php.net/password_hash 它们位于php.net/password_verify和php.net/password_hash


There is another issue, you're using MySQL, mysql is incredibly old and even deprecated at this point, it is advised you move over to mysqli or even pdo . 还有一个问题,您正在使用MySQL,这时mysql的版本已经过时了,甚至已被弃用,建议您改用mysqli甚至pdo

Security Issue 2: Your code ( $result = mysql_query("SELECT passwd FROM usrs where usrname = '".$posted_username."'"); ) is vulnerable to MySQL Injection . 安全问题2:您的代码( $result = mysql_query("SELECT passwd FROM usrs where usrname = '".$posted_username."'"); )容易受到MySQL注入的攻击。

MySQL injection is where someone tries to cut off your query, and uses his own. MySQL注入是某人试图切断您的查询并使用自己的查询的地方。 Because you do not properly sanitise user input (never trust the user), The code you're actually executing is not what you may expect it to look like, and may even consist of multiple queries (that could, for example, drop your tables, or even attempt to look up some of those clear-text passwords). 因为您没有适当地清理用户输入(永远不要信任用户),所以实际执行的代码不是您期望的样子,甚至可能包含多个查询(例如,可以删除表) ,甚至尝试查找其中的一些明文密码)。

PDO has this covered for us, if you properly make use of the PDO wrapper (located at php.net/pdo), you won't have to worry about this at all. PDO为我们涵盖了这一点,如果您正确使用PDO包装器(位于php.net/pdo),则完全不必担心。 (Well, you do, but it's a whole lot easier to do it right after you get the hang of it). (嗯,您知道了,但是掌握了它之后,就容易得多了)。

There also is MySQLi, which is just MySQL_* improved. 还有MySQLi,它只是对MySQL_ *的改进。 It allows for OOP programming and is faster. 它允许OOP编程并且速度更快。 It doesn't sanitise user input for you, you'll have to make use of mysqli_real_escape_string($str) , $mysqli->real_escape_string($str) , or if you insist on using MySQL_* functions, mysql_real_escape_string($str) . 它不会为您清理用户输入,您必须使用mysqli_real_escape_string($str)$mysqli->real_escape_string($str) ,或者如果您坚持使用MySQL_ *函数,则必须使用mysql_real_escape_string($str)


I'll cut off for now, this is a lot of difficult information to process. 我现在要切断,这是很多难以处理的信息。 But I hope someone learnt something from it. 但我希望有人从中学到一些东西。 And if not, well that's a shame really. 如果没有,那真是太可惜了。 As you're really using a few very unsafe ways. 因为您实际上正在使用一些非常不安全的方法。 Given you may test locally, it's still a good thing to learn good practises. 由于您可以在本地进行测试,因此学习良好的实践仍然是一件好事。

G'day! G'day!

It might depend on how you're using $equal. 这可能取决于您如何使用$ equal。

strcmp returns 0 if they are equal ( https://secure.php.net/manual/en/function.strcmp.php ) 如果相等,则strcmp返回0( https://secure.php.net/manual/en/function.strcmp.php

so if you are using if ($equal ) it will fail (because equal was 0) 因此,如果您使用if($ equal),它将失败(因为equal为0)

try to use var_dump($equal) to see what the result is, and try: 尝试使用var_dump($ equal)来查看结果,然后尝试:

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

I ran into this same (or similar) issue when comparing passwords. 比较密码时,我遇到了相同(或相似)的问题。 strcmp() told me the two strings didn't match, == told me they didn't match... They definitely matched. strcmp()告诉我两个字符串不匹配,==告诉我它们不匹配...它们绝对匹配。

My issue is that mcrypt_decrypt() was returning a 32 character string regardless of how long the string actually was. 我的问题是, 无论该字符串实际有多长时间,mcrypt_decrypt()都会返回一个32个字符串。 Tre bizarre. 太奇怪了。

Sample var_dump() output was: 样本var_dump()输出为:

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

A simple trim() after decryption solved the issue. 解密后简单的trim()解决了这个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM