2011-02-18 48 views
6

我想能夠根據失敗的嘗試遏制登錄嘗試,但我有一些問題。如何限制登錄嘗試 - PHP&MySQL&CodeIgniter

我應該使用MySQL嗎? (請閱讀它可能會損壞DB)
我應該限制每個用戶,系統範圍還是系統範圍? (所以阻止普通人猜測密碼)
我該如何計算我的門檻? (所以它會自動適應變化/增長)
我該如何檢索這個閾值?查詢/計算緩存上的每次失敗或存儲?
我應該用什麼油門? (閱讀睡眠()可能最終導致服務器過度的響應)

有沒有人有一些示例代碼?

我很新,所以我很感激幫助! 謝謝

回答

5

phunction單獨使用APC來實現一個poor-man's throttling mechanism,這是我如何使用它:

// allow 60 requests every 30 seconds 
// each request counts as 1 (expensive operations can use higher values) 
// keep track of IPs by REMOTE_ADDR (ignore others) 

$throttle = ph()->Throttle($ttl = 30, $exit = 60, $count = 1, $proxy = false); 

if ($throttle === true) 
{ 
    // IP exceded 30 requests in the last 60 seconds, die() here 
} 

else 
{ 
    // $throttle is a float 
    // number of requests in the last 30 seconds/30 seconds 

    /* 
    1 req/30 = 0,033 sec 
    5 req/30 = 0,166 sec 
    10 req/30 = 0,333 sec 
    15 req/30 = 0,5 sec 
    20 req/30 = 0,666 sec 
    25 req/30 = 0,833 sec 
    30 req/30 = 1  sec 
    */ 

    usleep(intval(floatval($throttle) * 1000000)); 
} 

我就用這個我的前端控制器並將價值傳遞給我的路由方法,但這是另一回事。

底線是,如果您使用APC,您可以在內存中保持非常快的速度,並且內存消耗很少,因爲APC遵循FILO方法。如果你需要更高的超時時間,你可以考慮使用不是基於內存的東西。

BTW:MySQL使用MEMORY引擎支持表。


sleep()的問題:

安裝的模塊會吃約10 MB的每個實例RAM,避免超出可用RAM PHP典型的Apache Web服務器有一些Apache的設置您可以配置爲限制Apache能夠啓動的最大實例數。

問題是當你sleep(),該實例仍然活動,並有足夠的請求可能最終吃掉所有可用的插槽來啓動新的服務器,從而使您的網站無法訪問,直到一些未決的請求完成。

無法從PHP AFAIK中解決這個問題,所以最終取決於您。


的原則,是全系統的限制相同:

function systemWide($ttl = 86400, $exit = 360) 
{ 
    if (extension_loaded('apc') === true) 
    { 
     $key = array(__FUNCTION__); 

     if (apc_exists(__FUNCTION__) !== true) 
     { 
      apc_store(__FUNCTION__, 0, $ttl); 
     } 

     $result = apc_inc(__FUNCTION__, 1); 

     if ($result < $exit) 
     { 
      return ($result/$ttl); 
     } 

     return true; 
    } 

    return false; 
} 
+0

從我所瞭解的這是爲每個用戶節流是嗎?如果是這樣,你如何建議我實施全系統節流以防止分佈式攻擊? – RS7 2011-02-18 03:16:49

0

MySQL數據庫能夠處理請求/秒的音調,所以如果你沒有成千上萬的用戶,你不必擔心瓶頸。

您也可以使用sleep() 注意:PHP處理的用戶多於ASP.NET - 再次。如果你沒有成千上萬的用戶,你可以使用睡眠方法,而不用瓶頸。

我通常這樣做的方式是通過存儲登錄嘗試(IP,用戶ID和時間戳)。 將其存儲在一張桌子上,並在您感覺喜歡的時候重置桌子(在特定的尺寸或一天中的某個時間)。 如果某個用戶ID + IP在「一定時間內」的登錄嘗試次數多於一次,請將用戶重定向到一個頁面,告訴用戶他/她已經習慣了很多次嘗試,並且無法登錄接下來的15分鐘(或任何你想要的)。 有點「窗口」就像我猜,但它就像一個魅力:)

+0

@ user622470:MySQL的問題在於他不需要成千上萬的用戶,只有一個知道如何快速創建數千個連接的用戶。 – 2011-02-18 03:41:29

+0

您的攻擊者無法訪問您的MySQL,僅訪問您的網頁。 – hogni89 2011-02-18 19:02:56

1

登錄失敗的登錄嘗試的表是這樣的:

FailedLogins 
id 
timestamp 
ip 

用戶試圖登錄您每次檢查用戶的IP地址在最近的Y秒內是否有X次失敗的登錄嘗試次數。

如果用戶在Y秒內失敗X次,則顯示錯誤消息或驗證碼。