<kbd id="5sdj3"></kbd>
<th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>

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

    共 2391字,需瀏覽 5分鐘

     ·

    2022-03-18 18:05

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

    API 接口設(shè)計(jì)

    作者:InfoQ Man

    Token 設(shè)計(jì)

    Token 是服務(wù)端生成的一串字符串,以作客戶(hù)端進(jìn)行請(qǐng)求的一個(gè)令牌,當(dāng)?shù)谝淮蔚卿浐?,服?wù)器生成一個(gè) Token 便將此 Token 返回給客戶(hù)端,以后客戶(hù)端只需帶上這個(gè) Token 前來(lái)請(qǐng)求數(shù)據(jù)即可,無(wú)需再次帶上用戶(hù)名和密碼。

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

    Token 種類(lèi)

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

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

    USER Token(用戶(hù)令牌): 用于訪(fǎng)問(wèn)需要用戶(hù)登錄之后的接口,如:獲取我的基本信息、保存、修改、刪除等操作。獲取用戶(hù)令牌需要拿用戶(hù)名和密碼來(lái)?yè)Q。

    API 接口設(shè)計(jì)原則

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

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

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

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

    POST /recommend/cardlist

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

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

    一般來(lái)說(shuō),接口的版本管理一般有以下兩種方法:

    1. 在 URL 中加入 version 信息,如下述;
    2. 在 HTTP header 加入 version 信息,這樣就等于只有一個(gè)接口,但是具體的不同版本的業(yè)務(wù)邏輯由后臺(tái)區(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)用門(mén)檻

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

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

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

    {

    "code" : 0,

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

    "message" : "string"

    }

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

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

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

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

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

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

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

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

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

    6.3.時(shí)間戳機(jī)制

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

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

    整個(gè)流程如下:

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

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

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

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

    5、服務(wù)端寫(xiě)一個(gè)過(guò)濾器對(duì) token、timestamp 和 sign 進(jìn)行驗(yàn)證,只有在 token 有效、timestamp 未超時(shí)、緩存服務(wù)器中不存在 sign 三種情況同時(shí)滿(mǎn)足,本次請(qǐng)求才有效。

    6.4.隨機(jī)數(shù)機(jī)制

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

    6.5.黑名單機(jī)制

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

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

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

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

    7、冪等性

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

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

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

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

    API 接口管理

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

    1. 維護(hù)不及時(shí);
    2. 與代碼不同步;
    3. 歸檔后“便束之高閣”;
    4. 接口文檔跟代碼沒(méi)有互動(dòng);
    5. 文本檢索無(wú)法建立全局搜索,需要額外借助工具。

    為了解決上述的問(wèn)題,需要建立一套行之有效的接口管理體系,該體系的目標(biāo)是:

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

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

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


    往期推薦

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

    魚(yú)皮的項(xiàng)目視頻被狗曝光了。。。

    這代碼誰(shuí)寫(xiě)的,太可怕了!

    前后端分離,千萬(wàn)別再搞錯(cuò)了!

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

    瀏覽 111
    點(diǎn)贊
    評(píng)論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報(bào)
    評(píng)論
    圖片
    表情
    推薦
    點(diǎn)贊
    評(píng)論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報(bào)

    <kbd id="5sdj3"></kbd>
    <th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>
    狠狠爱天天日 | 日皮在线视频 | 国产一a毛一a毛A免费看图 | 色五月成人视频 | 日韩无码日韩有码 |