生活随笔
收集整理的這篇文章主要介紹了
如何设计登录接口,十分钟内连续登录5次失败,需要等待30分钟才能登录
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正常業務里的實現不能這樣搞,合適的方法是走緩存,比如使用redis,我當時就只有原生Java API能用,請大家把這個當成算法題來看待
常言道:字數越短問題越大。
??今天阿里的面試官小哥哥讓我實現一個登錄接口,同一個用戶10分鐘內連續登陸5次失敗,則需要等到30分鐘才能登陸。
??當然大佬估計一看到這種題目會很難過,一丁點算法都沒有,妙解沒意思。我上來就被唬住了。登錄接口?10分鐘內連續5次??等待30分鐘才能登陸???登陸驗證????
??問號一下子就冒出來了,當然最開始我想定義一個變量firstFailTime來記錄第一次失敗的時間,再仔細一想不對啊,firstFailTime是動態的額,要不斷變化,單一個變量不好實現啊,第一次登錄失敗可以記錄,但如果出現前十分鐘失敗了4次,第11分鐘又失敗了一次的話,firstFailTime應該往后取第二次失敗登錄的時間啊,我總不能手動定義100個變量吧。。。面試官看到估計臉都綠了。恨不得給我一個Mysql數據表,把每次登陸都給存下來,這樣就可以很方便的查出某個時間區間登陸的情況。
??不慌,咱們雖然不是大佬,但一點一點分析還是可以的,沉住氣!等等,剛剛說到數據庫存所有的登錄數據??其實思考到上面已經快接近了,我不能手動創建100個變量,但我可以用一種數據結構依次記錄登錄失敗的時間啊,突然想到LRU算法對不對!!能從數據順序看出來時間順序的數據結構不就是鏈表嗎!!!還有登錄驗證的問題,不如偷個懶,用一個boolean控制。解決,cool~
P.S:我沒考慮開多個線程去測試,因為我個人感覺用戶登錄不會出現在高并發的環境里,幾萬個人同時登陸同一個賬號想想就離譜…但為了保險起見我還是給map加了synchronize關鍵字
package exam
;import java
.util
.LinkedList
;
public class Person {private static final int
RESET_TIME = 30;private static final int
DURATION = 10;private static final int
MAX_TIMES = 5;private String id
;private int failCount
;private long firstFailTime
;private LinkedList
<Long
> times
;private boolean lock
;public String
getId() {return id
;}public void setId(String id) {this.id
= id
;}public int
getFailCount() {return failCount
;}public void setFailCount(int failCount) {this.failCount
= failCount
;}public long
getFirstFailTime() {return firstFailTime
;}public void setFirstFailTime(long firstFailTime) {this.firstFailTime
= firstFailTime
;}public LinkedList
<Long
> getTimes() {return times
;}public void setTimes(LinkedList<Long> times) {this.times
= times
;}public Person() {}public Person(String id, int failCount, long firstFailTime, LinkedList<Long> times, boolean lock) {this.id
= id
;this.failCount
= failCount
;this.firstFailTime
= firstFailTime
;this.times
= times
;this.lock
= false;}public void isValid(){long thisTime
= System
.currentTimeMillis() / 1000;System
.out
.println("第一次登錄失敗時間" + thisTime
);if(thisTime
> firstFailTime
+ RESET_TIME){this.failCount
= 1;firstFailTime
= thisTime
;times
= new LinkedList<>();times
.addLast(thisTime
);this.lock
= false;return;}else{ if (lock
){System
.out
.println("賬戶鎖定,請" + RESET_TIME + "分鐘后再來");return;}while(!times
.isEmpty() && thisTime
> times
.getFirst() + DURATION){times
.removeFirst();this.failCount
--;this.firstFailTime
= times
.isEmpty() ? thisTime
: times
.getFirst();}if(this.failCount
>= 5 && thisTime
< firstFailTime
+ DURATION){System
.out
.println("10分鐘內密碼錯誤大于等于5次,登錄失敗");times
.addLast(thisTime
);this.lock
= true;}else if(failCount
< MAX_TIMES){this.failCount
++;System
.out
.println("密碼錯誤" + this.failCount
+ "次");times
.addLast(thisTime
);}}}
}
package exam
;import java
.util
.HashMap
;
import java
.util
.LinkedList
;
import java
.util
.Map
;
public class FlowLimit {private static Map
<String
, Person
> map
= new HashMap<>();public static void login(String id, boolean flag){if (flag
){return;}else{Person p
= null;synchronized (map) {p
= map
.get(id
);if (p
== null){p
= new Person(id
, 0, System
.currentTimeMillis() / 1000,new LinkedList<>(), false);map
.put(id
, p
);return;}p
.isValid();}}}public static void main(String[] args) {for(int i
= 0; i
< 20; i
++){login("aaa", false);}}
}
總結
以上是生活随笔為你收集整理的如何设计登录接口,十分钟内连续登录5次失败,需要等待30分钟才能登录的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。