Friday, October 2, 2015

[好文] 如何減低垃圾Request對主資料庫的影響

如何減低垃圾Request對主資料庫的影響

內文備份:

在今天國殤日,來淺談一下如何減低垃圾Request對主資料庫的影響吧~
首先,我們思考一下像BOT(誤)魔獸世界的點數卡系統:
用戶在便利店買到點卡得到密碼後,便在系統輸入密碼換取商品。
只要有利益的地方,便總會有cracker來random try去試試看會不會成功換取到商品的。
1。 首先,正常用戶應該不會長期+大量輸入點卡密碼錯誤的。所以,系統可以記錄一下用戶在24小時內錯誤輸入了多少次密碼,比如說如果錯掉10次以上便鎖掉戶口,明天請早。這樣便可以極大幅地增加cracker的操作成本。
不過,這些「輸入錯誤資訊」其實商業價值接近零,丟失了也沒有太大所謂;而且,生存期極短(只有24小時)。所以,其實這些資訊沒有必要存放到RDBMS的,使用Redis去存便好~
2。 「BOT世界」有大量用戶是每天有大量時間沒事幹的白目;即使限制每24小時只能錯10次;10萬個白目一天便能產生100萬個垃圾request的。如果點卡密碼只是單純的隨機亂碼,系統每個request都需要查詢RDBMS才知道其密碼真偽,RDBMS便要每天接受100萬個沒有任何商業價值的查詢。
所以,這些點卡密碼的產生方法一般都是:
    1 隨機亂碼
    2 使用某加密方法加密
當application server收到用戶的點卡密碼時,他只需要對這個密碼試試看解密。解密失敗的,便立即知道這個點卡密碼一定是錯誤的;解密正確的話,才查詢RDBMS看看密碼是否相符。
這樣,絕大部份白目的亂猜的Request也不會產生對RDBMS的流量~
---------------------------------
到正題:
(耐心看完文章的人有糖吃~)
其實如果把以上的東西延伸到Http Session上,會產生極奇妙的效果耶~
HttpSession傳統(老一代)作法:
1。 用戶把username / password傳到web server
2。 webserver隨機生產一個足夠長的隨機string token給回用戶,並且把這個(token, userId, expirationTime)存放於Redis / 任何能被所有webserver讀取的檔案空間
3。 用戶之後所有Request都在HTTP authorization header附上這個token,webserver用這個token在Redis中拿回userId和expirationTime
這個手法的缺點是:
1。 每一個Request,都需要查詢Redis。固然,Redis可以無限加開機台的。不過,這也會是錢啊!
2。 垃圾亂猜的Request也需要Redis的查詢
3。 如果Redis當掉,使用那台Redis的用戶的HTTP session立即失效,需要再login
---------------------------------
HttpSession(現代)作法:
1。 用戶把username / password傳到web server
2。 webserver產生一個jwt token,並且把(userId, expirationTime)放到這個jwt token上,然後使用RSA加密。然後把token傳回用戶。
(因為RSA證書只存放於伺服器,所以用戶沒可能偽造/改動)
3。 用戶之後所有Request都在HTTP authorization header附上這個token。webserver使用RSA證書解密,成功的話便知道userId,也知道這jwt是否已過期。
4。 每個Response中,伺服器都會把更新過expirationTime的新jwt token在http header中傳回用戶,用戶之後的Request應該使用新的token。
5。 安全起見,伺服器的RSA證書至少至少每一個月更換一次,以防cracker在偷聽到足夠多的通信後能破解出伺服器上的RSA證書。
(註:更換RSA證書時,會有grace period的,grace period其間新舊證書並行。否則丟了舊的RSA證書時,還在手持舊RSA證書的用戶便立即要重新證入了)
這個手法沒什麼缺點的(否則jwt也不會變成web server的de facto standard),唯一煩人的地方,便是每個月便要更換RSA證書=。=

No comments:

Post a Comment