1. 程式人生 > >如何設計一個牛逼的API介面

如何設計一個牛逼的API介面

在日常開發中,總會接觸到各種介面。前後端資料傳輸介面,第三方業務平臺介面。一個平臺的前後端資料傳輸介面一般都會在內網環境下通訊,而且會使用安全框架,所以安全性可以得到很好的保護。這篇文章重點討論一下提供給第三方平臺的業務介面應當如何設計?我們應該考慮哪些問題? ![](https://img2020.cnblogs.com/blog/1719198/202010/1719198-20201016202953711-1715594493.png) 主要從以上三個方面來設計一個安全的API介面。 ## 一 安全性問題 安全性問題是一個介面必須要保證的規範。如果介面保證不了安全性,那麼你的介面相當於直接暴露在公網環境中任人蹂躪。 ### 1.1 呼叫介面的先決條件-token 獲取token一般會涉及到幾個引數`appid`,`appkey`,`timestamp`,`nonce`,`sign`。我們通過以上幾個引數來獲取呼叫系統的憑證。 `appid`和`appkey`可以直接通過平臺線上申請,也可以線下直接頒發。`appid`是全域性唯一的,每個`appid`將對應一個客戶,`appkey`需要高度保密。 `timestamp`是時間戳,使用系統當前的unix時間戳。時間戳的目的就是為了減輕DOS攻擊。防止請求被攔截後一直嘗試請求介面。伺服器端設定時間戳閥值,如果請求時間戳和伺服器時間超過閥值,則響應失敗。 `nonce`是隨機值。隨機值主要是為了增加`sign`的多變性,也可以保護介面的冪等性,相鄰的兩次請求`nonce`不允許重複,如果重複則認為是重複提交,響應失敗。 `sign`是引數簽名,將`appkey`,`timestamp`,`nonce`拼接起來進行md5加密(當然使用其他方式進行不可逆加密也沒問題)。 `token`,使用引數`appid`,`timestamp`,`nonce`,`sign`來獲取token,作為系統呼叫的唯一憑證。`token`可以設定一次有效(這樣安全性更高),也可以設定時效性,這裡推薦設定時效性。如果一次有效的話這個介面的請求頻率可能會很高。`token`推薦加到請求頭上,這樣可以跟業務引數完全區分開來。 ### 1.2 使用POST作為介面請求方式 一般呼叫介面最常用的兩種方式就是GET和POST。兩者的區別也很明顯,GET請求會將引數暴露在瀏覽器URL中,而且對長度也有限制。為了更高的安全性,所有介面都採用POST方式請求。 ### 1.3 客戶端IP白名單 ip白名單是指將介面的訪問許可權對部分ip進行開放。這樣就能避免其他ip進行訪問攻擊,設定ip白名單比較麻煩的一點就是當你的客戶端進行遷移後,就需要重新聯絡服務提供者新增新的ip白名單。設定ip白名單的方式很多,除了傳統的防火牆之外,spring cloud alibaba提供的元件sentinel也支援白名單設定。為了降低api的複雜度,推薦使用防火牆規則進行白名單設定。 ### 1.4 單個介面針對ip限流 限流是為了更好的維護系統穩定性。使用redis進行介面呼叫次數統計,ip+介面地址作為key,訪問次數作為value,每次請求value+1,設定過期時長來限制介面的呼叫頻率。 ### 1.5 記錄介面請求日誌 使用aop全域性記錄請求日誌,快速定位異常請求位置,排查問題原因。 ### 1.6 敏感資料脫敏 在介面呼叫過程中,可能會涉及到訂單號等敏感資料,這類資料通常需要脫敏處理,最常用的方式就是加密。加密方式使用安全性比較高的`RSA`非對稱加密。非對稱加密演算法有兩個金鑰,這兩個金鑰完全不同但又完全匹配。只有使用匹配的一對公鑰和私鑰,才能完成對明文的加密和解密過程。 ## 二 冪等性問題 冪等性是指任意多次請求的執行結果和一次請求的執行結果所產生的影響相同。說的直白一點就是查詢操作無論查詢多少次都不會影響資料本身,因此查詢操作本身就是冪等的。但是新增操作,每執行一次資料庫就會發生變化,所以它是非冪等的。 冪等問題的解決有很多思路,這裡講一種比較嚴謹的。提供一個生成隨機數的介面,隨機數全域性唯一。呼叫介面的時候帶入隨機數。第一次呼叫,業務處理成功後,將隨機數作為key,操作結果作為value,存入redis,同時設定過期時長。第二次呼叫,查詢redis,如果key存在,則證明是重複提交,直接返回錯誤。 ## 三 資料規範問題 ### 3.1 版本控制 一套成熟的API文件,一旦釋出是不允許隨意修改介面的。這時候如果想新增或者修改介面,就需要加入版本控制,版本號可以是整數型別,也可以是浮點數型別。一般介面地址都會帶上版本號,http://ip:port//v1/list。 ### 3.2 響應狀態碼規範 一個牛逼的API,還需要提供簡單明瞭的響應值,根據狀態碼就可以大概知道問題所在。我們採用http的狀態碼進行資料封裝,例如200表示請求成功,4xx表示客戶端錯誤,5xx表示伺服器內部發生錯誤。狀態碼設計參考如下: | 分類 | 描述 | | ---- | -------------------------------------------- | | 1xx | 資訊,伺服器收到請求,需要請求者繼續執行操作 | | 2xx | 成功 | | 3xx | 重定向,需要進一步的操作以完成請求 | | 4xx | 客戶端錯誤,請求包含語法錯誤或無法完成請求 | | 5xx | 服務端錯誤 | 狀態碼列舉類: ```java public enum CodeEnum { // 根據業務需求進行新增 SUCCESS(200,"處理成功"), ERROR_PATH(404,"請求地址錯誤"), ERROR_SERVER(505,"伺服器內部發生錯誤"); private int code; private String message; CodeEnum(int code, String message) { this.code = code; this.message = message; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } ``` ### 3.3 統一響應資料格式 為了方便給客戶端響應,響應資料會包含三個屬性,狀態碼(code),資訊描述(message),響應資料(data)。客戶端根據狀態碼及資訊描述可快速知道介面,如果狀態碼返回成功,再開始處理資料。 響應結果定義及常用方法: ```java public class R implements Serializable { private static final long serialVersionUID = 793034041048451317L; private int code; private String message; private Object data = null; public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public Object getData() { return data; } /** * 放入響應列舉 */ public R fillCode(CodeEnum codeEnum){ this.setCode(codeEnum.getCode()); this.setMessage(codeEnum.getMessage()); return this; } /** * 放入響應碼及資訊 */ public R fillCode(int code, String message){ this.setCode(code); this.setMessage(message); return this; } /** * 處理成功,放入自定義業務資料集合 */ public R fillData(Object data) { this.setCode(CodeEnum.SUCCESS.getCode()); this.setMessage(CodeEnum.SUCCESS.getMessage()); this.data = data; return this; } } ``` ## 總結 本篇文章從安全性、冪等性、資料規範等方面討論了API設計規範。除此之外,一個好的API還少不了一個優秀的介面文件。介面文件的可讀性非常重要,雖然很多程式設計師都不喜歡寫文件,而且不喜歡別人不寫文件。為了不增加程式設計師的壓力,推薦使用swagger或其他介面管理工具,通過簡單配置,就可以在開發中測試介面的連通性,上線後也可以生成離線文件用於管理API。 ## 點關注、不迷路 如果覺得文章不錯,歡迎**關注**、**點贊**、**收藏**,你們的支援是我創作的動力,感謝大家。 如果文章寫的有問題,請不要吝嗇,歡迎留言指出,我會及時核查修改。 如果你還想更加深入的瞭解我,可以微信搜尋「**Java旅途**」進行關注。回覆「**1024**」即可獲得學習視訊及精美電子書。每天7:30準時推送技術文章,讓你的上班路不在孤獨,而且每月還有送書活動,助你提升硬