API防重放機制

說說API的防重放機制

咱們在設計接口的時候,最怕一個接口被用戶截取用於重放攻擊。重放攻擊是什麼呢?就是把你的請求原封不動地再發送一次,兩次...n次,通常正常的請求都會經過驗證進入到正常邏輯中,若是這個正常邏輯是插入數據庫操做,那麼一旦插入數據庫的語句寫的很差,就有可能出現多條重複的數據。一旦是比較慢的查詢操做,就可能致使數據庫堵住等狀況。redis

這裏就有一種防重放的機制來作請求驗證。數據庫

timestamp+nonce

咱們經常使用的防止重放的機制是使用timestamp和nonce來作的重放機制。api

timestamp用來表示請求的當前時間戳,這個時間戳固然要和服務器時間戳進行校訂過的。咱們預期正常請求帶的timestamp參數會是不一樣的(預期是正常的人每秒至多隻會作一個操做)。每一個請求帶的時間戳不能和當前時間超過必定規定的時間。好比60s。這樣,這個請求即便被截取了,你也只能在60s內進行重放攻擊。過時失效。服務器

可是這樣也是不夠的,還有給攻擊者60s的時間。因此咱們就須要使用一個nonce,隨機數。ui

nonce是由客戶端根據足夠隨機的狀況生成的,好比 md5(timestamp+rand(0, 1000)); 它就有一個要求,正常狀況下,在短期內(好比60s)連續生成兩個相同nonce的狀況幾乎爲0。url

服務端

服務端第一次在接收到這個nonce的時候作下面行爲:設計

  1. 去redis中查找是否有key爲nonce:{nonce}的string
  2. 若是沒有,
    1. 考慮作時間戳判斷,即認爲客戶端和服務端的時間差別不該該大於閾值(上述的60s,根據業務場景設置合理值),注意控制好時區Locale。
    2. 則建立這個key,把這個key失效的時間和驗證timestamp失效的時間一致,好比是60s。
  3. 若是有,說明這個key在60s內已經被使用了,那麼這個請求就能夠判斷爲重放請求。

示例

那麼好比,下面這個請求:rest

http://a.com?uid=123&timestamp=1480556543&nonce=43f34f33&sign=80b886d71449cb33355d017893720666接口

這個請求中國的uid是咱們真正須要傳遞的有意義的參數md5

timestamp,nonce,sign都是爲了簽名和防重放使用。

timestamp是發送接口的時間,nonce是隨機串,sign是對uid,timestamp,nonce(對於一些rest風格的api,我建議也把url放入sign簽名)。簽名的方法能夠是md5({祕要}key1=val1&key2=val2&key3=val3...)

服務端接到這個請求:

  1. 先驗證sign簽名是否合理,證實請求參數沒有被中途篡改
  2. 再驗證timestamp是否過時,證實請求是在最近60s被髮出的
  3. 最後驗證nonce是否已經有了,證實這個請求不是60s內的重放請求
相關文章
相關標籤/搜索