現在的應用系統中,大部分密碼存儲都是采用md5加密后存儲,常用的登錄基本流程如下:
1、前端web頁面用戶輸入賬號、密碼,點擊登錄。
2、請求提交之前,web端首先通過客戶端腳本如javascript對密碼原文進行md5加密。
3、提交賬號、md5之后的密碼
4、請求提交至后端,驗證賬號與密碼是否與數據庫中的一致,一致則認為登錄成功,反之失敗。
上述流程看似安全,認為傳輸過程中的密碼是md5之后的,即使被監聽截取到,由於md5的不可逆性,密碼明文也不會泄露。其實不然!監聽者無需解密出密碼明文即可登錄!監聽者只需將監聽到的url(如:http://****/login.do?method=login&password=md5之后的密碼&userid=登錄賬號)重放一下,即可冒充你的身份登錄系統。
較安全的登錄流程
1、進入登陸頁面時,生成一個隨機碼(稱之為鹽值),在客戶端頁面和session中各保存一份。
2、客戶端提交登錄請求時,將md5之后的密碼與該隨機碼拼接后,再次執行md5,然后提交(提交的密碼=md5(md5(密碼明文)+隨機碼))。
3、后端接收到登錄請求后,將從數據庫中查詢出的密碼與session中的隨機碼拼接后,md5運算,然后與前端傳遞的結果進行比較。
該登錄方式,即使登錄請求被監聽到,回放登錄URL,由於隨機碼不匹配(監聽者的session中的隨機碼與被監聽者的session中的隨機碼相同概率可忽略),無法登錄成功。
該登錄方式,由於傳輸的密碼是原密碼md5之后與隨機碼再次md5之后的結果,即使監聽者采用暴力破解的方式,也很難解密出密碼明文。
更安全的登錄流程
考慮到密碼輸入的方便性,好多用戶的密碼都設置的很短,並且不夠復雜,往往是6位數字字母組合,這樣的密碼md5之后保存到數據庫,一旦數據庫數據泄露,簡單密碼的md5結果很容易通過暴力破解的方式給解密出來!同時為了方便用戶登錄的方便性,我們的系統一般不可能要求用戶設置很長、很復雜的密碼!怎么辦?加固定鹽值。
1、系統設置一個固定的鹽值,該鹽值最好足夠復雜,如:1qaz2wsx3edc4rfv!@#$%^&**qqtrtRTWDFHAJBFHAGFUAHKJFHAJHFJHAJWRFA
2、用戶注冊、修改密碼時,將用戶的原始密碼與我們的固定鹽值拼接,然后做md5運算。
3、傳遞至后端,保存進數據庫(數據庫中保存的密碼是用戶的原始密碼拼接固定鹽值后,md5運算后的結果)。
4、登錄時,將用戶的原始密碼與我們的固定鹽值進行拼接,然后做md5運算,運算后的結果再拼接上我們的隨機碼,再次md5運算,然后提交。
5、后端接收到登錄請求后,將從數據庫中查詢出的密碼與session中的隨機碼拼接后,md5運算,然后與前端傳遞的結果進行比較。
該登錄方式可以認為是很安全的登錄方式了。
進一步完善
1、加登錄驗證碼,可預防人為地暴力登錄破解,為方便合法用戶的正常登錄,可設置密碼輸入錯誤次數達到3次后再出現驗證碼。
2、賬戶鎖定,如果用戶密碼輸入錯誤次數達到一定量后(如6次),則可以鎖定該賬號,為了方便合法用戶的正常登錄,可以設置成一小時后自動解鎖。