如何設計一個安全可靠的 API 接口?
CSDN · 程式 ·

如何設計一個安全可靠的 API 接口?

RESTAPI接口設計過程中,我們需要考慮如何讓鑒權變得更安全可靠,

作者 | 阿文

責編 | 屠敏

出品 | CSDN(ID:CSDNnews)

最近幾年,隨著RESTful API開始風靡,使用HTTP header來傳遞認證令牌似乎變得理所應當,通過 RESTful 的API 接口設計簡化了系統架構, 減少了耦合性, 可以讓所有模塊各自獨立的進行改進。

不過,在實際的REST API 接口設計過程中,我們需要考慮如何讓鑒權變得更安全可靠,例如不會被第三方惡意請求或者保證傳輸過程中的數據安全以及防止重複提交,本文就一起聊一聊。

少了耦合性,可以讓所有模塊各自獨立的進行改進。不過,在實際的

傳統的Session 認證方式

首先,我們說一些傳統的認證方式,眾所周知,HTTP 協議是一種無狀態的協議,而這就代表著如果用戶向我們的應用提供了用戶名和密碼來進行用戶認證,那麼下一次請求時,用戶還要再一次進行用戶認證才行,因為我們並不能知道是哪個用戶發出的請求,所以為了讓我們的應用能識別是哪個用戶發出的請求,我們只能在伺服器存儲一份用戶登錄的信息,這份登錄信息會在響應時傳遞給瀏覽器,告訴其保存為cookie,以便下次請求時發送給我們的應用,這樣我們的應用就能識別請求來自哪個用戶了,這就是傳統的基於session認證。

而這種方式有很多問題:

首先,占用資源,這種方式需要每個用戶經過認證之後,都要在服務端做一次記錄,以方便用戶下次請求的鑑別,通常而言session都是保存在內存中,而隨著認證用戶的增多,服務端的開銷會明顯增大。

其次,擴展性差: 客戶端認證之後,服務端做認證記錄,如果認證的記錄被保存在內存中的話,這代表著用戶下次請求還必須要請求在這台伺服器上,這樣才能拿到授權的資源,在一些分布式的場景下會限制了負載均衡器的能力,會限制了應用的擴展能力。

第三,容易遭受攻擊: 這種基於cookie來進行用戶識別的認證方式, 很容易被截獲,用戶就會很容易受到跨站請求偽造的攻擊。

得理所應當,通過RESTful的API接口設計簡化了系統架構,減

基於Token 的鑒權方式

由於session 認證的諸多問題,因此出現了基於token 的鑒權方式,這種方式不需要在服務端去保留用戶的認證信息或者會話信息。這就代表著基於token認證機制的應用不需要去考慮用戶在哪一台伺服器登錄了,這就為應用的擴展提供了便利。

基於token 鑒權的工作流程如下:

  • 首先,客戶端通過用戶名密碼來請求對應的API接口

  • 第二,伺服器會驗證用戶的信息

  • 第三,伺服器通過驗證後會發送token給客戶端

  • 第四,客戶端存儲token,並在每次請求時附送上這個token值

  • 第五,服務端驗證token值,並返回數據

這種方式的典型代表就是JWT(Json web token , 它是為了在網絡應用環境間傳遞聲明而執行的一種基於JSON的開放標準((RFC 7519),該token被設計為緊湊且安全的,特別適用於分布式站點的單點登錄(SSO)場景。JWT的聲明一般被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便於從資源伺服器獲取資源,也可以增加一些額外的其它業務邏輯所必須的聲明信息,該token也可直接被用於認證,也可被加密。

它的特點如下:

  • 體積小(一串字符串)。因而傳輸速度快

  • 傳輸方式多樣。可以通過 HTTP 頭部(推薦)/URL/POST 參數等方式傳輸

  • 嚴謹的結構化。它自身(在 payload 中)就包含了所有與用戶相關的驗證消息,如用戶可訪問路由、訪問有效期等信息,伺服器無需再去連接資料庫驗證信息的有效性,並且 payload 支持應用定製

  • 支持跨域驗證,多應用於單點登錄

JWT通常由三部分組成:

  • 頭信息(header)

  • 消息體(payload)

  • 簽名(signature)

如下所示:

// Header { "alg": "HS256", "typ": "JWT" }

// Payload { // reserved claims "iss": "a.com", "exp": "1d", // public claims "http://a.com": true, // private claims "company": "A", "awesome": true }

// $Signature HS256(Base64(Header) + "." + Base64(Payload), secretKey)

// JWT JWT = Base64(Header) + "." + Base64(Payload) + "." + $Signature

其工作流程如下:

  • 首先,客戶端通過發送HTTP 請求把帳號密碼發送給服務短,通常使用的是POST請求, 伺服器會校驗帳號與密碼是否合法,如果一致,則根據密鑰生成一個 token 並返回,客戶端收到這個 token 並保存在本地。在這之後,需要訪問一個受保護的路由或資源時,只要附加上 token(通常使用 Header 的 Authorization 屬性)發送到伺服器,伺服器就會檢查這個 token 是否有效,並做出響應。

  • 服務端接收到 token 之後,會逆向構造過程,解碼出 JWT 的三個部分,這一步可以得到 sign 的算法及 payload,結合服務端配置的 secretKey,可以再次進行 $Signature 的生成得到新的 $Signature,與原有的 $Signature 比對以驗證 token 是否有效,完成用戶身份的認證,驗證通過才會使用 payload 的數據。

TfulAPI開始風靡,使用HTTPheader來傳遞認證令牌似乎變

如何保證接口安全性

要想實現接口的安全性,我們可以做到以下幾點:

首先,我們需要採用HTTPS 對傳輸過程中的數據進行加密,避免使用HTTP 這種明文傳輸的協議,防止數據直接暴露在公網中,在使用HTTPS的同時要保證時間安全可靠的加密方法和SSL 協議,目前主流的是TLS1.2 和最新的TLS1.3。同時要對證書進行校驗,因為即使是HTTPS協議,證書也是能夠被偽造的。

其次,對接口設計一般會加入 token、timestamp和sign 這些參數,不同的參數有自己不同的用途:

  • timestamp,即時間戳,它是客戶端調用接口時傳入的當前時間戳,時間戳的目的是用於防止DoS攻擊。每次調用接口時接口都會判斷伺服器當前系統時間和接口中傳的的timestamp的差值,如果這個差值超過某個設置的時間,例如設置的時間是3分鐘,那麼這個請求將被攔截掉,如果在設置的超時時間範圍內,是不能阻止DoS攻擊的。timestamp機制只能減輕DoS攻擊的時間,縮短攻擊時間。如果黑客修改了時間戳的值可通過sign簽名機制來處理。

  • sign,即簽名,通常用於參數簽名,防止參數被非法篡改,最常見的是修改金額等重要敏感參數, sign的值一般是將所有非空參數按照升續排序然後+token+key+timestamp+nonce(隨機數)拼接在一起,然後使用某種加密算法進行加密,這種方式的好處就是,當被劫持後,修改其中的參數值,然後再繼續調用接口,雖然參數的值被修改了,但是因為攻擊者並不清楚sign是如何計算出來的,所以即可是篡改參數的值,但沒法修改sign的值,當伺服器調用接口前會按照sign的規則重新計算出sign的值然後和接口傳遞的sign參數的值做比較,如果相等表示參數值沒有被篡改,如果不等,表示參數被非法篡改了,則不會返回真實的響應信息。

  • 此外,接口設計時候要實現冪等性操作,所謂的冪等性操作就是為了防止重複性運算,我們可以將生成的簽名和key保存到redis 中,並且設置超時時間,過期自動刪除,當有重複的值存在則不會處理,就可以防止重複提交,從而保證請求結果一致性。

其使用流程如下:

  1. 接口調用方(客戶端)向接口提供方(伺服器)申請接口調用帳號,申請成功後,接口提供方會給接口調用方一個AppKey和一個APP Secret參數

  2. 調用方申請App Key 和 App Secret 在生成請求時,將參數拼接後進行加密,例如使用HMAC-SHA256 或MD5加密,然後將 App Key, 加密結果追加到請求上。sign=加密(appId + timestamp + key)

  3. 服務收到請求後,根據App Key識別出調用方,解密得到參數以及對時間進行對比,判斷是否超時,然後從字典中查詢到對應的App Secret,與請求參數拼接、加密,與請求中的簽名進行對比,簽名結果相同的為合法請求。

以上就是給API 接口設計的一些建議,僅供參考,在實際的應用中還可以追加一些公共的參數,例如Host、接口的版本等等參數去進行校驗保證接口的安全性。

|CSDN(ID:CSDNnews)最近幾年,隨著RES
作者|阿文責編|屠敏出品
聲明:文章觀點僅代表作者本人,PTTZH僅提供信息發布平台存儲空間服務。
喔!快樂的時光竟然這麼快就過⋯
繼續其他精彩內容吧!
more