如何設計一個良好的API接口


提供給第三方的業務接口應該如何設計呢?需要從哪些方面考慮?以及如何實現這些方面?

1、標准化

  RESTful 

 

2、安全性

  1)請求token

    token作為調用系統的憑證。token可以設置一次有效(安全性最高),不過推薦設置時效性,減少獲取獲取token接口的請求頻率。 token建議放在請求頭上,這樣可以跟業務參數完全區分開。

    獲取token一般會涉及的幾個參數:appId、appKey、timestamp、nonce(requestId)、sign

    appIdappKey通過開發平台申請和下發,appId即應用Id,是請求方的全局唯一的標識,一個appId對應一個客戶,appKey需要高度保密,用於接口加密時拼裝appKey作為加密串,不作為網絡傳輸。

    timestamp是時間戳,目的是為了減輕DOS攻擊。防止請求被攔截后一直嘗試請求接口。服務器設置時間戳閥值(5s),如果請求時間戳和服務器時間超過閥值,則響應失敗。

    nonce(requestId)是隨機值,目的是為了增加sign的多變性,也可以保護接口的冪等性,相鄰的兩次請求nonce不允許重復,如果重復則認為是重復提交,響應失敗。(將每次請求的nonce參數存儲到緩存中,每次請求去緩存中查詢是否存在,如果存在則認為是非法請求)

    sign是參數簽名,將appId,nonce,timestamp,還有其余非空請求參數,按照字母升序排列,然后使用URL鍵值對的格式(key1=value1&key2=value2)拼接起來,最后再拼接上appKey,組成待簽名串;然后進行md5加密生成簽名(或其他不可逆加密方式(如RSA2),有的情況要求先對待簽名串進行UrlEncode,然后再加密生成簽名)

    請求攜帶appId和sign,只有擁有合法的身份appId和正確的簽名sign才放行。

  2)加密簽名

    對敏感入參進行AES加密,防止數據泄漏

    對所有請求參數拼裝后進行RSA簽名,防止參數遭篡改。請求進來之后先驗證簽名,簽名不匹配直接返回失敗

    (對於客戶端與服務端的交互,AES密鑰應使用動態密鑰,每次由客戶端生成AES密鑰,並使用公鑰進行加密傳給服務端(RSA私鑰保存在服務端))

  3)客戶端IP白名單

    限流是為了更好的維護系統穩定性。防止接口遭惡意大量頻繁調用(盜刷)。使用Redis進行接口調用次數統計,ip+接口地址作為key,訪問次數作為value,每次請求value+1,設置過期時長來限制接口的調用頻率。

  4)限流

    可使用阿里的Sentinel限流工具:https://github.com/alibaba/Sentinel

 

3、冪等性

  冪等性是指任意多次請求的執行結果和一次請求的執行結果所產生的影響相同。

  如查詢刪除是冪等的,新增修改是非冪等的。

  解決方案:

    服務方提供一個生成全局唯一隨機數token的接口,客戶端在調用業務接口前先向服務方發送請求獲取token,在客戶端獲取token的時候,將token存入redis中。

      ① 服務方提供獲取token的接口,token可以是uuid

      ② 客戶端在調用業務接口前先調用接口獲取token

      ③ 服務方在客戶端獲取token時,生成token,並將token 作為 key,客戶端用戶信息作為value,保存在redis中,然后返回token

      ④ 客戶端請求業務接口時,將獲取的token放在header(最好放在header中)或者作為請求參數請求接口

      ⑤ 服務端收到請求后,從headers中拿到token,然后根據token到redis中查找該key是否存在

      ⑥ 如果存在,業務處理成功后,從redis中刪除此token。如果不存在,說明重復調用,返回請勿重復操作即可

      注意:從redis中查詢token和刪除token,要保證原子性,應使用redis分布式鎖

  https://www.cnblogs.com/yangyongjie/p/13724165.html

 

4、規范標准

  1)加密、簽名方式規范

    敏感字段采用AES加密,模式為CBC,具體算法為 AES/CBC/PKCS5Padding。

    簽名的作用:對數據進行簽名后,可以保證數據完整性,機密性和發送方角色的不可抵賴性,可以有效防止請求信息信息被篡改

    簽名方式采用RSA2(簽名算法為SHA256WithRSA,要求RSA密鑰的長度至少為2048位),步驟如下:

      1)篩選並排序

        獲取所有請求參數,不包括字節類型參數(如文件,字節流),剔除sign參數和值為空的參數,並且參數名和參數值前后不要帶有空格,並按照參數名的第一個字符的鍵值ASCII碼遞增排序(字母升序排序),如果遇到相同字符則按照第二個字符的鍵值 ASCII 碼遞增排序,以此類推;

      2)拼接

        將排序后的參數與其對應值,組合成“參數=參數值”的格式,並且把這些參數用 & 字符連接起來,此時生成的字符串為待簽名字符串

      3)簽名

        最后對待簽名串簽名,並進行BASE64編碼。然后將生成的簽名賦值給sign參數,拼接到請求參數中

 

  2)請求方式為POST

    除了sign參數外,其他參數全部以JSON格式放在body中。

    請求方需要對sign進行UrlEncode,且Content-Type:application/json; charset=utf-8

  3)接口返回規范

    返回類型為JSON格式,包含狀態碼code、描述msg、響應數據data,返回碼和描述提前定義好。必要的話,對響應的參數進行簽名賦值給sign參數一並返回。

  4)統一參數校驗和驗簽,打印請求日志

    使用AOP全局記錄請求日志(請求接口URL,請求參數),響應日志。設置請求線程號,用於快速定位異常請求位置,排查問題原因

    使用另一個AOP統一進行參數非空校驗、簽名校驗、token校驗,不通過直接返回失敗,不進入業務代碼。

 

 

END.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM