2012-04-09 202 views
1

当您验证注册用户时,您提出请求,例如,一个例子,我发现:PHP验证注册用户

$user = $_POST['user']; 
$pw = $_POST['password']; 

$sql = "SELECT user,password FROM users 
    WHERE user='$user' 
    AND password='$pw' 
    LIMIT 1"; 
$result = mysql_query($sql); 

if (mysql_num_rows($result)){ 
    //we have a match! 
}else{ 
    //no match 
} 

现在会有什么好处或末端具有LIMIT 1的任何一点? 为什么你需要选择用户和密码时,你可以选择user_id?

岂不

SELECT user_id FROM users 
WHERE user = '{$user}' 
AND password = '{$pw}' 

是完全相同的,但物流短代码?

编辑:思考这个小细节让我找到了一个更多的检查,以防止黑客。 不应该有一个以上的用户使用相同的电子邮件和密码,因此如果他们以某种方式提供密码123' OR password = '*'(或类似的逻辑),这将危及我的查询,没有限制将帮助,因为下一步我可以指望

if (count($result) > 1) { 
    echo "we got hacked"; 
else 
    <proceed...> 

回答

1

最有可能的是,你将有一个独特的user列,所以LIMIT 1是没有必要的 - 你不会有超过1行。

在这种情况下,它可能是一个装饰元素 - 自我解释语法来告诉程序员读取代码,该查询预计返回不超过一行。

除了你的问题,我强烈建议使用一些密码加密,例如MD5()。教你如何存储一个简单的密码不是最好的...

+0

是的,我这样做,但md5本身并不安全,因为许多网站与数据库保存散列和原始字符串我认为像crc32(md5(散列(“sha256”,$ _ POST ['密码'])))会好得多 – JohnA 2012-04-09 13:38:32

4

假设你只有在数据库中单列为每个用户名/密码对,LIMIT子句通过在找到第一个匹配之后停止搜索来提高性能,主要是在与ORDER BY子句一起使用时。

MySQL manual

如果使用LIMIT ROW_COUNT与ORDER BY,MySQL的结束,因为它已经找到了排序结果的第一行ROW_COUNT,而不是排序整个结果将尽快整理。如果使用索引完成排序,则速度非常快。

0

在大多数情况下,您的表格将保存唯一的用户名,因此您将始终返回1或0行。就你的代码而言,它并没有什么不同。即使你有多行返回,你的代码仍然可以正常工作,因为你只是检查行的存在,而不是检查了多少行(但它会是错误的,因为你不知道哪个用户实际登录了) 。

基本上它只是告诉MySQL停止搜索满足WHERE条件的第一行之后的表。在某些情况下,即使这可能是多余的(例如,如果您在“user”字段上有UNIQUE索引)。

还有一件事与您的问题无关:请不要将此代码用于除了学习以外的任何内容。它充满了安全漏洞。谷歌的“SQL注入”和“安全地存储密码”,然后再将此代码投入生产。

-1

杉杉你需要从注射消毒字符串:

class main{ 
public function sanitize($str,$remove_nl=true) 
     { 
      stripslashes($str); 

      if($remove_nl) 
      { 
       $injections = array('/(\n+)/i', 
        '/(\r+)/i', 
        '/(\t+)/i', 
        '/(%0A+)/i', 
        '/(%0D+)/i', 
        '/(%08+)/i', 
        '/(%09+)/i' 
        ); 
       $str = preg_replace($injections,'',$str); 
      } 

      return $str; 
     } 
} 

下你的代码:

$main_class = new main(); 

$user = $main_class->sanitize(trim($_POST['user'])); 
$pw = $main_class->sanitize(trim($_POST['password'])); 

$sql = "SELECT * FROM `users` WHERE `user`='".$user."' AND `password`='".$pw."' LIMIT 0,1"; 
$result = mysql_query($sql) or die(mysql_error()); 
$count = mysql_num_rows($result); 

if($count > 0){ 
    //we have a match! 
}else{ 
    //no match 
} 
+0

我可以只使用mysql_real_escape_string()吗?为什么它必须是类和对象,而不仅仅是函数? – JohnA 2012-04-09 13:39:39

+0

是的,但是这个real_escape_string不会像我在示例中的'$ injections'数组中那样删除特殊符号。 其实我强烈建议使用'mysqli'来防止默认表达式的所有注入,并且使用'mysqli'你不需要从特殊符号中转义字符串 – 2012-04-09 14:10:38

1

你可以阅读“SQL Injection: How To Prevent Security Flaws In PHP/MySQL”,看看您的登录会如何没有适当的措施是无用的。

其他的一切都被上面更明智的海报解答了。

+0

好的,谢谢,但是我现在并没有问它是什么只是样本查询问题是关于它的最后一行,而不是一般的安全。到目前为止,我使用mysql_real_escape_string()来处理输入数据。 – JohnA 2012-04-09 13:43:04

+0

然后,如果您只需要授权部分,请继续按照您认为合适的方式将其缩短。尽管如此,最后的LIMIT 1是一个有效的优化。 SQL“不知道”是一个登录函数,也不知道有一条记录(或没有)可以找到,并且会搜索整个表中的匹配项。 – CosminO 2012-04-09 13:55:34