我正在为网站设置一个登录信息(也许我这样做的方式是错误的,但这是另一个问题)。
我这样做的方式是这样的:
我可以让数据库连接。我可以从数据库中提取密码。我可以从帖子中收集价值。但我无法比较这两个值 - 它总是说它们不相等,即使它们回应它们也是如此。
收集我使用的已发布值:
$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。
答案 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()解决了这个问题。