在大前端時代的安全性一文中講了 Web 前端和 Native 客戶端如何從數據安全層面作反爬蟲策略,本文接着以前的背景,將從 API 數據接口的層面講一種技術方案,實現數據安全。前端
API 接口存在不少常見的安全性問題,常見的有下面幾種狀況git
因此針對上述的問題也有一些解決方案:程序員
關於 HTTPS 證書雙向認證和 Web 端反爬蟲技術方案均在大前端時代的安全性一文中有具體講解。接下來引出本文主角:防重放github
在以前的文章也講過,HTTPS 依舊能夠被抓包,形成安全問題。抓包工具下數據依舊是裸奔的,能夠查看Charles 從入門到精通文中講的如何獲取 HTTPS 數據。算法
假如經過網絡層高手截獲了 HTTPS 加證書認證後的數據,因此須要對請求參數作簽名。步驟以下數據庫
由於中間人不知道簽名密鑰,因此即便攔截到請求,修改了某項參數,可是沒法獲得正確的簽名 signature,這樣構造的一個請求,會被服務器斷定爲一次非法請求。segmentfault
在工程師文化中,咱們要作一個事情,就首先要對這個事情下個定義。咱們才能知道作什麼、怎麼作。緩存
理論上,一個 API 接口請求被收到,服務會作校驗,可是當一個合法請求被中間人攔截後,中間人原封不動得重複發送該請求一次或屢次,這種重複利用合法請求進行得攻擊被成爲重放。安全
重放會形成服務器問題,因此咱們須要針對重放作防重放。本質上就是如何區別去一次正常、合法的請求。服務器
理論上,客戶端發起一次請求,到服務端接收到這個請求的時間,業界斷定爲不超過60秒。利用這個特徵,客戶端每次請求都加上 timestamp1,客戶端將 timestamp1 和其餘請求參數一塊兒簽名獲得 signature,以後發送請求到服務器。
假如中間人攔截到請求,修改了 timestamp 或者其餘的任何參數,可是不知道密鑰,因此服務器依舊斷定爲非法請求。 中間人從抓包、篡改參數、發起請求的過程通常來講大於60秒,因此服務器依舊會斷定爲非法請求。
基於 timestamp 的設計缺陷也很明顯,種種緣由下,60秒內的請求,會鑽規則漏洞,服務器斷定爲一次合法請求。
既然時間戳會有漏洞,那麼新方案是基於隨機字符串 nonce。也就是說每次請求都加入一個隨機字符串,而後將其餘參數一塊兒利用密鑰加密獲得簽名 signature。服務端收到請求後
可是該方案也有缺點,由於當次的請求都須要和集合中去搜索匹配,因此該集合不能太大,否則匹配算法特別耗時,接口性能下降。因此不得不按期刪除部分 nonce 值。可是這樣的狀況下,被刪除的 nonce 被利用爲重放攻擊,服務器斷定爲合法請求。
假設服務器只保存24小時內請求的 nonce,該存儲仍舊是一筆不小的開銷。
根據 timestamp 和 nonce 各自的特色:timestamp 沒法解決60秒內的重放請求;nonce 存儲和查找消耗較大。因此結合2者的特色,便有了 「timestamp + nonce 的防重放方案」。
步驟:
該集合不該該直接操做文件或者數據庫,不然服務端 IO 太多,形成性能瓶頸。能夠是 mmap 或者其餘內存到文件的讀寫機制。根據場景能夠選擇樂觀鎖、悲觀鎖。
其中有一個 timestamp 的問題,服務器會將請求參數中的 timestamp 判斷差值,其中一個致命的缺點是服務器的時間和客戶端的時間是存在時間差的,固然你也能夠經過校驗時間戳解決此問題。時間同步請繼續看下面部分。
客戶端和服務端的時間同步在不少場景下很是重要,舉幾個例子,這些場景都是常常發生的。
因此該現象在計算機領域有很是廣泛,有解決方案。
若是精度要求不高的狀況下:先請求服務器上的時間 ServerTime,而後記錄下來,同時記錄當前的時間 LocalTime1;須要獲取當前的時間時,用最新的當前時間 (LocalTime2 - LocalTime1 + ServerTime)
拿 iOS 端舉例:
NSSystemClockDidChangeNotification
監測系統時間發生改變,若變化則從新獲取接口,進行時同步若是須要精度更高,好比 100納秒的狀況,則須要使用 NTP(Network Time Protocol)網絡時間協議、PTP (Precision Time Protocol)精確時間同步協議了。
NTP、PTP 不在本文的範疇,感興趣的能夠查看這篇文章