我要限制使用者一小時內登陸只能密碼輸錯12次,如果在最近一小時內累計密碼錯誤超過12次就直接不能登入,如何用memcache實現,不用mysql,因為碰到mysql的login log表越來越大,之前mysql的實現方式太慢了
回複內容:
我要限制使用者一小時內登陸只能密碼輸錯12次,如果在最近一小時內累計密碼錯誤超過12次就直接不能登入,如何用memcache實現,不用mysql,因為碰到mysql的login log表越來越大,之前mysql的實現方式太慢了
如果你不需要記錄使用者登陸的曆史詳情,只是想要限制登陸次數就非常簡單
為每個使用者建立一個特別的key(舉個例子,user_login_count_${使用者ID}
每次登陸的時候拿到使用者名稱,就去memcache去取這個key的value,如果發現其值已經超過12,則在此時報錯說明只能嘗試12次
如果不存在這個key,那麼通過set建立,並把值記為1,expire時間設定為3600秒
如果登入失敗,那麼對這個key對應的value進行increment的操作,並重新設定逾時時間為3600秒
如果登陸成功,則直接清除這個key的內容
因為 @vimac 的答案沒有解決最近一小時問題,以下僅提供個思路,細節還可以完善
get($key) or array();$allow_times = 12;if(! checkAllowTimes($login_failed, $allow_times)){ throw new Exception("allow times max", 1);}if(! passValid($user_id, $password)){ array_unshift($login_failed, time()); // 最多存 12 條記錄 if(count($login_failed) > $allow_times){ $login_failed = array_slice($login_failed, 0, $allow_times); } $mem->set($key, $login_failed, 3600);}else{ // 登入成功刪除失敗記錄,取決於是連續失敗還是累計失敗? $mem->delete($key); // ...}function passValid($user_id, $password){ // ... // 虛擬碼 return true or false;}function checkAllowTimes($login_failed, $allow_times){ $last_hour = strtotime('1 hours ago'); for($i = 0; $i < count($login_failed); $i++){ // 如果已經登入失敗 12 次 if($i >= $allow_times - 1){ return false; } // 1 小時前的登入記錄不檢索 if($login_failed[$i] <= $last_hour){ return true; } } return true;}