2012-04-09 243 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