咱們在開發接口的時候一般會考慮接口的安全性,好比說咱們一般會要求請求的url攜帶一個通過算法加密的簽名sign
到服務端進行驗證,若是驗證經過,證實請求是合法的。好比如下的url:
redis
http://wokao66.com/in.json?uid=7&sign=xxxxx
算法
其中sign
的經常使用加密算法爲MD5
,MD5
算法是一種不可逆算法,也就是說你加密以後就不能解密了。這一般要求通信雙方約定好一個私鑰appSecret
,這個私鑰是約定好的,不能在網絡上進行傳輸。但單單有這個加密是遠遠不夠的,好比說我是一名黑客,我抓包了你當前執行成功的請求信息,咱們假設爲request-1
,既然你都執行成功了,也就是說你的此次請求的全部參數都是合法的,那麼做爲黑客的我,我就想能不能將你request-1
的請求數據再封裝成另一個請求request-2
,而後再去請求接口,若是此時系統未做任何處理,那麼系統確定是認爲request-2
是合法的,確定仍是會放行,但至於業務上成不成功,那麼是另一個問題了,假若在執行業務前須要進行一個相對耗時的數據庫操做,那麼大量的request-2
,request-3
勢必會使服務器癱瘓。數據庫
醬紫,可能語言難以理解,我畫個圖先:json
首先正常的請求系統會要求校驗,當你的合法請求被黑客攔截以後,黑客就會重複地發送該合法請求,從而達到欺騙系統的目的!這種重複利用合法請求進行攻擊成爲重放。緩存
重放攻擊的原理其實很簡單,無非就是系統沒有對合法請求進行惟一性校驗
。什麼意思呢?就是說系統要知道你第一次的合法請求request-1
不能被重複執行,要保證每次請求的惟一性。那麼怎麼去防止重放攻擊呢?安全
參考網絡上的解決方案,大概有如下兩種方式:服務器
這種方式的作法就是,首先咱們認爲一次HTTP請求從發出到到達服務器的時間是不會超過60s的,當你發送一個請求時必須攜帶一個時間戳timestamp
,假設值爲10,當請求到達服務器以後,服務器會取出當前時間,假設爲t2=80,很明顯t2-timestamp>60s
,那麼服務器就認爲請求不合法。網絡
號外號外,這個時間戳是須要加入MD5
加密簽名的,否則黑客修改了時間戳t2=20
,那不就是白費功夫了。app
爲何這樣作有效?運維
首先黑客從抓包到發起請求通常會超過60s,再者咱們不需擔憂黑客修改了時間戳timestamp
,由於若是修改了時間戳,那麼對應的簽名sign
也就失效了,由於MD5
是不可逆的,你想僞造MD5
,必須知道雙方約定的密鑰appSecret
。
缺點:
nonce
上面說到時間戳是有缺點的,那麼咱們加入一個隨機數nonce
,每次成功請求,服務器會保存當前成功請求的隨機數nonce
,好比存放在redis
和數據庫中,當請求再次進到服務器,先驗證時間戳是否有效,若是有效,再判斷攜帶的隨機數nonce
是否在緩存或者數據庫中已經存在,若是存在,則認爲請求非法。
但你會發現,若是系統請求很是多,這個存放nonce
的緩存也好,數據庫也好勢必會愈來愈大,那麼咱們只須要保存服務器當前時間60秒內的nonce
值便可。
缺點:
nonce
絕對惟一record
的方案什麼是基於record
的驗證方式呢?就是說我如今不須要隨機數,我利用MD5加密的惟一性,採用多維度(多個字段),將每次請求的記錄保存到數據庫中,每次請求先校驗簽名記錄是否存在,若是存在,則認爲請求非法,不存在,則將MD5
簽名結合其餘參數一塊兒保存到數據庫中。固然這裏也能夠結合時間戳只保存60s內的數據。
第三點主要是不考慮採用隨機數機制,同時對本身業務能夠有不一樣的擴展,或者說加入業務參數方便運維監控等。
綜合上面幾種方案,都有缺點,其中一個致命的缺點是服務器的時間和客戶端的時間是存在時間差的,固然你也能夠經過校驗時間戳解決此問題。
謝謝閱讀。