<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          這才叫 API 接口設(shè)計!

          共 2391字,需瀏覽 5分鐘

           ·

          2022-03-18 18:05

          大家好,我是魚皮,前段時間在 星球 里看到了一位小伙伴分享的文章《API 接口設(shè)計最佳實踐》,我也讀了一遍,寫的確實好,給大家分享一下,相信對后端開發(fā)的小伙伴會很有幫助。

          API 接口設(shè)計

          作者:InfoQ Man

          Token 設(shè)計

          Token 是服務(wù)端生成的一串字符串,以作客戶端進行請求的一個令牌,當?shù)谝淮蔚卿浐螅?wù)器生成一個 Token 便將此 Token 返回給客戶端,以后客戶端只需帶上這個 Token 前來請求數(shù)據(jù)即可,無需再次帶上用戶名和密碼。

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

          Token 種類

          API Token(接口令牌): ?一般用于訪問不需要用戶登錄的接口,如登錄、注冊、一些基本數(shù)據(jù)的獲取(如信用卡官網(wǎng)的如信用卡費率相關(guān)信息)等。獲取接口令牌需要拿 appId、timestamp 和 sign 來換;其中該 sign 值一般是把 timestamp、key 和對應(yīng)的參數(shù)先進行字母排序再進行 MD5 加密(有時候會加鹽),即 sign=MD5(排序(timestamp+key+參數(shù)));

          • 假設(shè) API 的請求參數(shù)為 channel:T,discount:90%,quantities:10,根據(jù)參數(shù)名稱的 ASCII 碼表的順序排序即為:channel:T,discount:90%,quantities:10。
          • 接著把排序后的參數(shù)名和參數(shù)值拼裝在一起為:channelTdiscount90%quantities10。
          • 把拼裝好的字符串采用 utf-8 編碼,使用簽名算法對編碼后的字節(jié)流進行摘要,即為 sign=md5(channelTdiscount90%quantities10);
          • 最后,Token=hex(appid+sign+timestamp+salt),即可獲得十六進制的一串字符,如“68656C6C6F776F726C64”。

          USER Token(用戶令牌): 用于訪問需要用戶登錄之后的接口,如:獲取我的基本信息、保存、修改、刪除等操作。獲取用戶令牌需要拿用戶名和密碼來換。

          API 接口設(shè)計原則

          1、明確協(xié)議規(guī)范

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

          2、統(tǒng)一接口路徑規(guī)范

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

          POST /recommend/cardlist

          3、統(tǒng)一接口版本管理

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

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

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

          POST v1/recommend/cardlist

          Nginx的路由分發(fā):
          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、為你的接口設(shè)定調(diào)用門檻

          為調(diào)用你的系統(tǒng)分配一個 ID 和 key,針對每個請求對 ID 和 key 進行校驗,避免在企業(yè)內(nèi)網(wǎng)中的其他系統(tǒng)只要知道接口被可以隨意調(diào)用。

          5、接口返回規(guī)范

          返回數(shù)據(jù)盡量統(tǒng)一規(guī)范,務(wù)必包括:返回碼、返回信息、數(shù)據(jù)。

          {

          "code" : 0,

          "content" : "string", ?<- 這里為 JSON

          "message" : "string"

          }

          6、接口安全規(guī)范

          當我們開發(fā)的接口需要暴露到公網(wǎng),這樣的風(fēng)險跟我們在企業(yè)內(nèi)網(wǎng)暴露給其他系統(tǒng)調(diào)用的風(fēng)險是不可同日而語的。其中有很多風(fēng)險需要我們一一解決。以下僅提供能想到的:

          6.1.數(shù)據(jù)如何防止被看到?

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

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

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

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

          6.2.數(shù)據(jù)如何防止給篡改?

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

          6.3.時間戳機制

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

          客戶端在第一次訪問服務(wù)端時,服務(wù)端將 sign 緩存到 Redis 中并把有效時間設(shè)定為跟時間戳的超時時間一致;如果有人使用同一個 URL 再次訪問,如果發(fā)現(xiàn)緩存服務(wù)器中已經(jīng)存在了本次的 sign,則拒絕服務(wù);如果在 Redis 中的 sign 失效的情況下,有人使用同一個 URL 再次訪問,則會被時間戳超時機制攔截。這樣的話,就可以避免 URL 被別人截獲后的重放攻擊。

          整個流程如下:

          1、客戶端通過用戶名密碼登錄服務(wù)器并獲取 Token

          2、客戶端生成時間戳 timestamp,并將 timestamp 作為其中一個參數(shù)

          3、客戶端將所有的參數(shù),包括 Token 和 timestamp 按照自己的算法進行排序加密得到簽名 sign

          4、將 token、timestamp 和 sign 作為請求時必須攜帶的參數(shù)加在每個請求的 URL 后邊(http://url/request?token=123×tamp=123&sign=123123123)

          5、服務(wù)端寫一個過濾器對 token、timestamp 和 sign 進行驗證,只有在 token 有效、timestamp 未超時、緩存服務(wù)器中不存在 sign 三種情況同時滿足,本次請求才有效。

          6.4.隨機數(shù)機制

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

          6.5.黑名單機制

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

          6.6.數(shù)據(jù)合法性校驗

          這里的數(shù)據(jù)合法性校驗主要指的是數(shù)據(jù)格式校驗和業(yè)務(wù)規(guī)則校驗。

          • 數(shù)據(jù)格式校驗:日期格式校驗、長度校驗、非空校驗等;
          • 業(yè)務(wù)規(guī)則校驗:如庫存校驗、身份證合法性校驗等。

          7、冪等性

          定義:在計算機中,表示對同一個過程應(yīng)用相同的參數(shù)多次和應(yīng)用一次產(chǎn)生的效果是一樣,這樣的過程即被稱為滿足冪等性。

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

          8、接口設(shè)計的一些最佳實踐

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

          API 接口管理

          一家公司的每個系統(tǒng)都會有各種各樣的接口,但是大部分公司,特別是傳統(tǒng)行業(yè)的公司的所謂接口文檔更多是當每個系傳統(tǒng)的 word 文本格式,這種傳統(tǒng)的格式有著人盡皆知的痛點:

          1. 維護不及時;
          2. 與代碼不同步;
          3. 歸檔后“便束之高閣”;
          4. 接口文檔跟代碼沒有互動;
          5. 文本檢索無法建立全局搜索,需要額外借助工具。

          為了解決上述的問題,需要建立一套行之有效的接口管理體系,該體系的目標是:

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

          業(yè)界有很多不同的 API 接口管理平臺,如去哪兒網(wǎng)的 YAPI 平臺、阿里某團隊開發(fā)的 RAP 平臺、Swagger、easyAPI 等等。各位小伙伴可以分享一下自己對這些平臺的使用感受~

          最后,歡迎大家加入魚皮的 編程學(xué)習(xí)圈子 ,和 3000 多名 小伙伴們一起交流學(xué)習(xí),向大廠大佬們 1 對 1 提問、跟著魚皮直播做項目(第二期回放已發(fā)布)~


          往期推薦

          別人看源碼,那我也要看!

          魚皮的項目視頻被狗曝光了。。。

          這代碼誰寫的,太可怕了!

          前后端分離,千萬別再搞錯了!

          哦,原來大廠是這樣發(fā)布應(yīng)用的!

          瀏覽 111
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  操逼视频免费观看网站 | 97人人干| 黄片豆花视频 | 草比视频91 | 淫色淫香网站 |