Nonce是由服務器生成的一個隨機數,在客戶端第一次請求頁面時將其發回客戶端;客戶端拿到這個Nonce,將其與用戶密碼串聯在一起並進行非可逆加密(MD5、SHA1等等),然后將這個加密后的字符串和用戶名、Nonce、加密算法名稱一起發回服務器;服務器使用接收到的用戶名到數據庫搜索密碼,然后跟客戶端使用同樣的算法對其進行加密,接着將其與客戶端提交上來的加密字符串進行比較,如果兩個字符串一致就表示用戶身份有效。這樣就解決了用戶密碼明文被竊取的問題,攻擊者就算知道了算法名和nonce也無法解密出密碼。
每個nonce只能供一個用戶使用一次,這樣就可以防止攻擊者使用重放攻擊,因為該Http報文已經無效。可選的實現方式是把每一次請求的Nonce保存到數據庫,客戶端再一次提交請求時將請求頭中得Nonce與數據庫中得數據作比較,如果已存在該Nonce,則證明該請求有可能是惡意的。
然而這種解決方案也有個問題,很有可能在兩次正常的資源請求中,產生的隨機數是一樣的,這樣就造成正常的請求也被當成了攻擊,隨着數據庫中保存的隨機數不斷增多,這個問題就會變得很明顯。所以,還需要加上另外一個參數Timestamp(時間戳)。
Timestamp是根據服務器當前時間生成的一個字符串,與nonce放在一起,可以表示服務器在某個時間點生成的隨機數。這樣就算生成的隨機數相同,但因為它們生成的時間點不一樣,所以也算有效的隨機數。
問題又來了,隨着用戶訪問的增加,數據庫中保存的nonce/timestamp/username數據量會變得非常大。對於這個問題,可選的解決方案是對數據設定一個“過期時間”,比如說在數據庫中保存超過一天的數據將會被清除。如果是這樣的,攻擊者可以等待一天后,再將攔截到的HTTP報文提交到服務器,這時候因為nonce/timestamp/username數據已被服務器清除,請求將會被認為是有效的。要解決這個問題,就需要給時間戳設置一個超時時間,比如說將時間戳與服務器當前時間比較,如果相差一天則認為該時間戳是無效的。
參考鏈接:http://www.cnblogs.com/bestzrz/archive/2011/09/03/2164620.html