天天看點

API防止重放的設計和思考

作者:IT知識分享官

最近公司有一個需求,需要針對來訪請求增加防重播攻擊政策,這算是一種安全架構上的設計,相信肯定很多公司都已經按照自身的也去情況進行了實作,每個公司肯定也有自己的做法,但是可以肯定的是,像這種安全架構層面上的東西大公司一般都不會洩露。網上參考來參考去也就那幾種,下面是我摘抄來自 API接口防止重播攻擊(重複攻擊)的内容。

定義

我們在進行API接口設計時,一般都要考慮接口的防止篡改攻擊和防止重播攻擊。重播攻擊(Replay Attacks)又稱重播攻擊、回放攻擊,是指攻擊者發送一個目的主機已接收過的包,來達到欺騙系統的目的,主要用于身份認證過程,破壞認證的正确性。重播攻擊可以由發起者,也可以由攔截并重發該資料的敵方進行。攻擊者利用網絡監聽或者其他方式盜取認證憑據,之後再把它重新發給認證伺服器。重播攻擊在任何網絡通過程中都可能發生,是計算機世界黑客常用的攻擊方式之一。

舉個例子,使用者發起一個付款請求,請求中帶着付款參數,攻擊者攔截了該請求,向伺服器重複的發送該請求,如果伺服器端沒有配置防止重播攻擊政策,則可能會進行多次付款,造成使用者損失。

常用的防止重播攻擊政策主要分為以下三種:

1、基于 timestamp 的方案

2、基于 token 的方案

3、基于 timestamp 和 token 的方案

基于 timestamp 的方案

在請求中增加 timestamp 參數要來表示請求時間戳,服務方端接收該請求後,根據目前時間生成一個接收時間戳,然後根據兩個時間戳的內插補點進行請求判定,如果內插補點大于指定的門檻值,則認為請求無效,否則請求通過。關于門檻值的標明,可以根據接口的響應速度進行适當的調整,一般預設為 60 秒。

僞代碼如下:

arduino           

複制代碼

if((接收時間戳-請求時間戳) > 60){ "請求失敗" } else { "請求通過" }

該方案要求請求和響應的雙方必須進行時間同步,如果服務的雙方本身存在時間上的差異,會對內插補點的計算産生影響,最後導緻請求的判定産生偏差。

缺點:通過上面的判定邏輯可以發現,在小于門檻值的時間段内是可以進行重複請求的,該方案不能保證請求僅一次有效。

基于 token 的方案

在請求中增加一個通過指定規則産生的 token,辨別請求的唯一性,服務方接收該請求後,先判斷緩存集合中是否存在該 token,如果存在則認為此次請求無效,否則将 token 放入緩存中,通過請求通過。

僞代碼如下:

arduino           

複制代碼

if(token 存在于緩存集合中){ "請求失敗" } else { 将 token 放入集合中 "請求通過" }

該方案要求 token 的生成規則要保證唯一性,如果 token 值重複,則會影響正常的請求通路。

缺點:token 存在于緩存中,而且沒有有效期設定,随着請求量的增加,緩存集合中 token 的數量會非常龐大,會占用系統的大量記憶體。為了解決這個問題,我們引入了基于 timestamp 和 token 的方案。

基于 timestamp 和 token 的方案

timestamp 解決 token 方案中緩存集合資料量大的問題,token 解決 timestamp 方案中一次性通路的問題。僞代碼如下:

arduino           

複制代碼

if((接收時間戳-請求時間戳) > 60秒){ "請求失敗" } if(token 存在于緩存集合中){ "請求失敗" } else { 将 token 放入集合中,緩存時間60秒 "請求通過" }

通過此種方式改進,即解決了驗證token一次性問題,又解決了token緩存的有效期問題。

總結

我個人想法:

第一種基于timestamp方案最大的問題是用戶端所處的不同時區時間是不一樣的,伺服器肯定都是以一個時區的時間進行比較的,但是用戶端時區卻是很多的,并且用戶端會随着時區不一樣獲得的時間也不一樣;如果一定要使用這種方式,還得在用戶端傳入所處的時區,然後服務端按照時區獲得時間進行比較,這對于服務端開發來說也是一個挑戰。

第二種和第三種其實沒有差太多,一個token緩存有過期時間,一個沒有過期時間的差別,這種兩種方案最大的挑戰是存放token的redis可能成為一個瓶頸。就拿日均流量1000萬PV的系統來說,每秒鐘就有115條token緩存産生,假設token緩存的有效時間為60s,那麼每60s将會有約7000條緩存産生和過期,這對于redis來說也是一個挑戰。

我們的選擇,我們選擇的是第三種方式。主要基于以下幾點考慮:1、我們的流量,整體項目日均pv在200w左右,峰值也不會查過1000w。2、我們将這種token緩存放在redis,并且在阿裡雲購買了可伸縮的redis服務,好處就是可以支援橫向擴容、對服務無感覺,萬一流量來了,我們就在買一台,3、開發成本簡單、可控,隻需要我們在目前的getway程式中把這個功能加上去即可。

最後,大規模、高并發項目究竟該如何實作api防重放呢?

繼續閱讀