API接口設計最佳實踐

目錄

目錄

前言

API接口設計

Token設計

API接口設計原則

1、明確協議規範

2、統一接口路徑規範

3、統一接口版本管理

4、爲你的接口設定調用門檻

5、接口返回規範

6、接口安全規範

7、冪等性

8、接口設計的一些最佳實踐

API接口管理



前言

最近團隊內部在做故障覆盤的時候發現有很多故障都是因爲接口設計不當導致的,這裏我就整理歸納一下在接口設計層面需要注意的地方。

API接口設計

 

Token設計

Token是服務端生成的一串字符串,以作客戶端進行請求的一個令牌,當第一次登錄後,服務器生成一個Token便將此Token返回給客戶端,以後客戶端只需帶上這個Token前來請求數據即可,無需再次帶上用戶名和密碼。

Token的值一般用UUID(算法比較著名的有雪花算法),當服務端接收到客戶端請求後會生成Token(一串字符,如etye0fgkgk4ca2ttdsl0ae9a5dd77471fgf),然後將Token作爲key將一些和Token關聯的信息作爲value保存到如Redis緩存數據庫中,同步把該Token返回給客戶端;後續該客戶端的請求都需要帶上這個Token,服務器收到請求後就會去緩存服務器中匹配這個Token是否存在,存在則調用接口,不存在返回接口錯誤。

Token種類

  • API Token(接口令牌): 一般用於訪問不需要用戶登錄的接口,如登錄、註冊、一些基本數據的獲取(如信用卡官網的如信用卡費率相關信息)等。獲取接口令牌需要拿appId、timestamp和sign來換;其中該sign值一般是把timestamp、key和對應的參數先進行字母排序再進行MD5加密(有時候會加鹽),即sign=MD5(排序(timestamp+key+參數));
  • 假設API的請求參數爲channel:T,discount:90%,quantities:10,根據參數名稱的ASCII碼錶的順序排序即爲:channel:T,discount:90%,quantities:10。
  • 接着把排序後的參數名和參數值拼裝在一起爲:channelTdiscount90%quantities10。
  • 把拼裝好的字符串採用utf-8編碼,使用簽名算法對編碼後的字節流進行摘要,即爲sign=md5(channelTdiscount90%quantities10);
  • 最後,Token=hex(appid+sign+timestamp+salt),即可獲得十六進制的一串字符,如“68656C6C6F776F726C64”。
     
  • USER Token(用戶令牌): 用於訪問需要用戶登錄之後的接口,如:獲取我的基本信息、保存、修改、刪除等操作。獲取用戶令牌需要拿用戶名和密碼來換。

API接口設計原則

1、明確協議規範

在設計初期需要明確雙方的通訊協議是TCP、HTTP、RPC,一般針對比較敏感的交易或者行業(如金融業),建議使用HTTPS協議以確保數據交互的安全。

2、統一接口路徑規範

建議採用Restful的風格,一般採用這樣的格式:控制器名/方法名。具體請參考以下例子:

POST /recommend/cardlist

3、統一接口版本管理

APP後臺邏輯總是處於變化當中,但是APP端(如安卓和ios)因爲涉及到應用市場的審覈問題,還有這些2C端的APP應用存在版本碎片化的問題,因此後臺暴露的接口需要在一段時間內支持不同版本的接口,一般方法是通過Nginx通過配置過濾根據接口的不同版本進行路由分發。

一般來說,接口的版本管理一般有以下兩種方法:

  1. 在URL中加入version信息,如下述;
  2. 在HTTP header加入version信息,這樣就等於只有一個接口,但是具體的不同版本的業務邏輯由後臺區分處理。

POST v1/recommend/cardlist

Nginx的路由分發:
server {
    listen 80;
    server_name vip.com;
    location /v1/ {
        proxy_pass http://129.0.0.1:8001/;
        proxy_redirect http://129.0.0.1:8001/   /v1/;
        proxy_set_header Host $host;
    }
    location /v2/ {
        proxy_pass http://129.0.0.1:8002/;
        proxy_redirect http://129.0.0.1:8002/   /v2/;
        proxy_set_header Host $host;
    }
}

server {
    listen 8001;
    allow 129.0.0.1;  
    deney all;
    server_name vip.com;
    root vip.com/v1/;
}

server {
    listen 8002;
    allow 129.0.0.1;  
    deney all;
    server_name vip.com;
    root vip.com/v2/;
}

 

4、爲你的接口設定調用門檻

爲調用你的系統分配一個ID和key,針對每個請求對ID和key進行校驗,避免在企業內網中的其他系統只要知道接口被可以隨意調用。

5、接口返回規範

返回數據儘量統一規範,務必包括:返回碼、返回信息、數據

{
  "code" : 0,
  "content" : "string",  <- 這裏爲JSON
  "message" : "string"
}

6、接口安全規範

當我們開發的接口需要暴露到公網,這樣的風險跟我們在企業內網暴露給其他系統調用的風險是不可同日而語的。其中有很多風險需要我們一一解決。以下僅提供能想到的:

6.1.數據如何防止被看到?

目前業界老生常談就是對稱加密和非對稱加密。

對稱加密:對稱密鑰在加密和解密的過程中使用的密鑰是相同的,常見的對稱加密算法有DES,AES;優點是計算速度快,缺點是在數據傳送前,發送方和接收方必須商定好祕鑰,然後使雙方都能保存好祕鑰,如果一方的祕鑰被泄露,那麼加密信息也就不安全了;

非對稱加密:服務端會生成一對密鑰,私鑰存放在服務器端,公鑰可以發佈給任何人使用;優點就是比起對稱加密更加安全,但是加解密的速度比對稱加密慢太多了;廣泛使用的是RSA算法;

目前主流的做法是在傳輸層使用https協議,http和tcp之間添加一層加密層(SSL層),這一層負責數據的加密和解密。https協議則是巧妙的利用上述兩種對稱加密方法;淺顯一點說就是客戶端和服務端建立三次握手連接過程中通過交換雙方非對稱公鑰,接着使用對方非對稱公鑰加密雙方約定好的對稱密鑰,這樣就只有雙方有這個對稱密鑰(這樣的非對稱加密可以保證很安全的把對稱密鑰給到對方)。後續雙方的報文溝通就可以使用該對稱密鑰進行加解密(這樣的對稱加密可以保證請求報文可以快速被解密處理,並在處理後被快速加密響應回去)。

6.2.數據如何防止給篡改?

這個時候我們需要對數據進行加簽,數據簽名平時用得比較多的是MD5,即將需要提交的數據通過某種方式組合和一個字符串,然後通過MD5生成一段加密字符串,這段加密字符串就是數據包的簽名。具體請看以下的圖。

數據加簽

6.3.時間戳機制

如果加密數據被抓包後被用於重放攻擊,我們怎麼辦?這個時候我們可以把解密後的URL參數中的時間戳與系統時間進行比較,如果時間差超過一定間距(如5分鐘)即認爲該報文被劫持並返回錯誤。但是,務必保證該時間戳的超時時間一定要跟sign保存的有效時間一致。

客戶端在第一次訪問服務端時,服務端將sign緩存到Redis中並把有效時間設定爲跟時間戳的超時時間一致;如果有人使用同一個URL再次訪問,如果發現緩存服務器中已經存在了本次的sign,則拒絕服務;如果在Redis中的sign失效的情況下,有人使用同一個URL再次訪問,則會被時間戳超時機制攔截。這樣的話,就可以避免URL被別人截獲後的重放攻擊。

整個流程如下:
1、客戶端通過用戶名密碼登錄服務器並獲取Token
2、客戶端生成時間戳timestamp,並將timestamp作爲其中一個參數
3、客戶端將所有的參數,包括Token和timestamp按照自己的算法進行排序加密得到簽名sign
4、將token、timestamp和sign作爲請求時必須攜帶的參數加在每個請求的URL後邊(http://url/request?token=123&timestamp=123&sign=123123123)
5、服務端寫一個過濾器對token、timestamp和sign進行驗證,只有在token有效、timestamp未超時、緩存服務器中不存在sign三種情況同時滿足,本次請求才有效。

 

6.4.隨機數機制

另外,一般會在URL參數上加上隨機數(即所謂的加鹽)並與6.3的時間戳機制組合使用以便提升防重複提交攻擊。

6.5.黑名單機制

針對同一個IP在短時間內頻繁請求的,可以通過Nginx進行過濾,同步可以在Nginx部署動態黑名單(即IP實時更新到黑名單庫),這樣可以防控少量的DDOS。但受限於判斷黑名單需要考慮多維度的信息,一般我們的Nginx儘量只做同一IP校驗,更多維度的黑名單校驗可以通過廠商去解決。

6.6.數據合法性校驗

這裏的數據合法性校驗主要指的是數據格式校驗和業務規則校驗。

數據格式校驗:日期格式校驗、長度校驗、非空校驗等;

業務規則校驗:如庫存校驗、身份證合法性校驗等。

7、冪等性

定義:在計算機中,表示對同一個過程應用相同的參數多次和應用一次產生的效果是一樣,這樣的過程即被稱爲滿足冪等性。

具體的解決方案有token機制、分佈式鎖、狀態機等方案;這裏引用一下之前看到的一篇文章,寫得比較詳細: https://blog.csdn.net/u011635492/article/details/81058153

8、接口設計的一些最佳實踐

  • 即使返回的JSON中某字段沒有值(即空值),也一定要返回該字段。同時前端也需做好這類情況的容錯處理;
  • 針對單頁面的多接口請求,爲避免擴大攻擊面,建議把多接口邏輯整合到一個接口,一個頁面直接調用該接口,以避免繞過部分接口進行攻擊;
  • 接口最好支持分頁;分頁一般有電梯式分頁(即一開始算好總頁數,優劣也一目瞭然)和遊標式分頁(即每次查詢會拿上一頁的最大的那個ID即cursor進行查詢,這種方式更適合類似以時間爲排序條件的互聯網單頁應用);
  • 針對你的接口提前做好限流;一般常用的限流有計數器、令牌桶、漏桶這三種。具體請參考接口中的幾種限流實現

 

API接口管理

一家公司的每個系統都會有各種各樣的接口,但是大部分公司,特別是傳統行業的公司的所謂接口文檔更多是當每個系傳統的word文本格式,這種傳統的格式有着人盡皆知的痛點:1)維護不及時;2)與代碼不同步;3)歸檔後“便束之高閣”;4)接口文檔跟代碼沒有互動;5)文本檢索無法建立全局搜索,需要額外借助工具。爲了解決上述的問題,需要建立一套行之有效的接口管理體系,該體系的目標是:

  1. 能夠進行接口文檔管理,作爲後續的接口治理的其中一部分;
  2. 能作爲接口測試的平臺,這樣能保證接口跟代碼是同步的;
  3. 支持文本檢索。

業界有很多不同的API接口管理平臺。如去哪兒網的YAPI平臺、阿里某團隊開發的RAP平臺、Swagger、Postman、easyAPI。針對這一些平臺的優劣對比,因爲目前暫時還沒有真正用起來不好去評價,各位有興趣的自行搜索學習。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章