2011-06-15 313 views
5

我想限制失敗的登錄嘗試次數。例如,如果某個特定用戶嘗試使用錯誤的用戶名或密碼登錄4次,我應該在第4次顯示CAPTCHA而不是屏蔽某些特定時間,並且除非他提供有效的用戶名和密碼,否則不斷顯示CAPTCHA。一旦用戶成功登錄,登錄嘗試將被重置爲零。限制失敗的登錄嘗試次數

是否從安全的角度來檢查用戶名而不是IP地址?這種方法是否可以在不使用數據庫的情況下實施?因爲我認爲我不需要存儲時間,因爲我只會顯示recaptcha? 請給出你的意見。

+1

http://stackoverflow.com/questions/580534/best-way-to-limit-and-record-login-attempts http://stackoverflow.com/questions/679756/limiting-user-login-attempts- in-php – Jacob 2011-06-15 12:23:54

回答

8

你不想使用數據庫'失敗的登錄數' - 檢查?然後只需使用一個cookie並檢查它。當然,他們可以將其刪除,但這很麻煩。

但是,我懷疑你已經從數據庫中獲取用戶名和密碼,爲什麼不在你登錄時獲取失敗登錄的最後一個號碼呢?

if (isset($_POST['submit_login'])) { 

    if (isset($_POST['username']) && isset($_POST['password'])) { 
     $username = mysql_real_escape_string($_POST['username']); 
     $password = mysql_real_escape_string($_POST['password']); 
     // id = unique primary key 
     $rs = mysql_query('SELECT id,Username,Password,Failed_logins,IP_address FROM Users WHERE Username = '.$username.''); 
     $num = mysql_num_rows($rs); 
     if ($num > 0) { 
      // I would add a password hash here to $password, and check against the hashed Password from the database 
      // But let's check the clean passwords 
      $row = mysql_fetch_array($rs); 
      if ($password == $row['Password']) { 
       // Successful login, set session or whatever you need 
       // Reset failed logins 
       mysql_query('UPDATE Users SET Failed_logins = 0 WHERE id = '.$row['id'].''); 
       header('location: success.php'); 
      } else { 
       // Failed password check 
       if ($row['Failed_logins'] > 3) { 
        // Redirect to captcha 
        header('location: captcha.php'); 
       } else { 
        $ip = $_SERVER['REMOTE_ADDR']; 
        if ($row['IP_address'] != $ip) { 
         // New ip adress, reset failed logins 
         $failed_logins = 0; 
        } else { 
         // Increment failed logins 
         $failed_logins = $row['Failed_logins']+1; 
        } 
        mysql_query('UPDATE Users SET Failed_logins = '.$failed_logins.',IP_address = '.$ip.' WHERE id = '.$row['id'].' '); 
       } // End check Failed_logins > 3 
      } 
     } else { 
      // No such Username found in database 
      $error = 'no_such_username'; 
     } // End username check from database 

    } else { 
     // Either username or password is missing 
     $error = 'incomplete_form'; 
    } // end check for username and password 

} // end main submit_login check 

就是這樣的。

編輯:

這是真的老代碼,我現在看到的一些問題吧。但是,至少您應該始終使用PDO(準備好的語句)在數據庫中插入數據。

+2

記得在成功登錄後重置'Failed_logins'。 – jensgram 2011-06-15 12:33:22

+0

是的,這很好。所以只有成功登錄後才能重置failed_login?所以即使一個人在一年後嘗試,也不會允許?我應該添加另一列像login_time並比較時間?可以說一個人只能在24小時內嘗試3次?這是個好主意嗎? – Roman 2011-06-15 12:40:31

+0

如果攻擊者持續提供不存在的用戶名,該怎麼辦? – Roman 2011-06-15 12:45:03

0

您應該將嘗試保存在數據庫中並檢查用戶。

1

你在保護什麼?

隨機的用戶專用內容,用戶名。

銀行信息(我懷疑..)或其他敏感數據,IP可能沒問題,只要你使用範圍。

你在問怎麼做,或者你應該用什麼?

1

您確實需要時間,您會如何確定登錄嘗試是否已過期?如果我在10年的時間內無法登錄4次,我會被阻止。您想阻止那些在短時間內嘗試多次登錄嘗試的人。

我建議您使用數據庫 - 因爲您將同時保存登錄的詳細歷史記錄。但是像memcached這樣基於內存的解決方案也足夠了。

詳細說明要實現哪種安全性:組合

結合使用的用戶名和IP地址,並將它們存儲到您的數據庫中。

  1. 使用用戶名登錄嘗試直接保護您的用戶免受企圖。
  2. 使用ip地址信息僅觀察檢測,並在需要時採取措施。
+0

感謝您的想法。現在,存儲用戶的用戶名或IP地址會更有幫助嗎?如果攻擊者繼續提供不存在的用戶名和密碼,會發生什麼情況? – Roman 2011-06-15 12:42:55

0

這樣做的最好方法是使用數據庫。

您需要在數據庫中創建一個單獨的表,這將存儲三個變量:

(一)IP地址(如該人試圖登錄) (B)的登錄嘗試 數( C)日期/時間(或:當前時間戳)

這種方法唯一的問題是與第一個變量:IP地址

如果該人是在網吧呢?或者使用公共無線網絡?還是熱點?或者,一所學校?辦公室? etc等

如果您阻止了IP地址,它會影響每個嘗試從該位置登錄您的網站的人。

如果您的網站涉及銀行,軍事裝置或五角大樓等問題,這不是問題。但是,如果你的網站是一個商業(購買和銷售,遊戲,無論),然後阻止一個特定的地址只會激怒你的客戶!