<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>

          如何設(shè)計(jì)一個(gè)牛逼的Java API接口?

          共 4182字,需瀏覽 9分鐘

           ·

          2020-09-26 14:02

          在日常開發(fā)中,總會(huì)接觸到各種接口。前后端數(shù)據(jù)傳輸接口,第三方業(yè)務(wù)平臺(tái)接口。一個(gè)平臺(tái)的前后端數(shù)據(jù)傳輸接口一般都會(huì)在內(nèi)網(wǎng)環(huán)境下通信,而且會(huì)使用安全框架,所以安全性可以得到很好的保護(hù)。這篇文章重點(diǎn)討論一下提供給第三方平臺(tái)的業(yè)務(wù)接口應(yīng)當(dāng)如何設(shè)計(jì)?我們應(yīng)該考慮哪些問題?

          主要從以上三個(gè)方面來設(shè)計(jì)一個(gè)安全的API接口。

          一 安全性問題

          安全性問題是一個(gè)接口必須要保證的規(guī)范。如果接口保證不了安全性,那么你的接口相當(dāng)于直接暴露在公網(wǎng)環(huán)境中任人蹂躪。

          1.1 調(diào)用接口的先決條件-token

          獲取token一般會(huì)涉及到幾個(gè)參數(shù)appidappkeytimestampnoncesign。我們通過以上幾個(gè)參數(shù)來獲取調(diào)用系統(tǒng)的憑證。

          appidappkey可以直接通過平臺(tái)線上申請,也可以線下直接頒發(fā)。appid是全局唯一的,每個(gè)appid將對應(yīng)一個(gè)客戶,appkey需要高度保密。

          timestamp是時(shí)間戳,使用系統(tǒng)當(dāng)前的unix時(shí)間戳。時(shí)間戳的目的就是為了減輕DOS攻擊。防止請求被攔截后一直嘗試請求接口。服務(wù)器端設(shè)置時(shí)間戳閥值,如果請求時(shí)間戳和服務(wù)器時(shí)間超過閥值,則響應(yīng)失敗。

          nonce是隨機(jī)值。隨機(jī)值主要是為了增加sign的多變性,也可以保護(hù)接口的冪等性,相鄰的兩次請求nonce不允許重復(fù),如果重復(fù)則認(rèn)為是重復(fù)提交,響應(yīng)失敗。

          sign是參數(shù)簽名,將appkeytimestampnonce拼接起來進(jìn)行md5加密(當(dāng)然使用其他方式進(jìn)行不可逆加密也沒問題)。

          token,使用參數(shù)appidtimestampnoncesign來獲取token,作為系統(tǒng)調(diào)用的唯一憑證。token可以設(shè)置一次有效(這樣安全性更高),也可以設(shè)置時(shí)效性,這里推薦設(shè)置時(shí)效性。如果一次有效的話這個(gè)接口的請求頻率可能會(huì)很高。token推薦加到請求頭上,這樣可以跟業(yè)務(wù)參數(shù)完全區(qū)分開來。

          1.2 使用POST作為接口請求方式

          一般調(diào)用接口最常用的兩種方式就是GET和POST。兩者的區(qū)別也很明顯,GET請求會(huì)將參數(shù)暴露在瀏覽器URL中,而且對長度也有限制。為了更高的安全性,所有接口都采用POST方式請求。

          1.3 客戶端IP白名單

          ip白名單是指將接口的訪問權(quán)限對部分ip進(jìn)行開放。這樣就能避免其他ip進(jìn)行訪問攻擊,設(shè)置ip白名單比較麻煩的一點(diǎn)就是當(dāng)你的客戶端進(jìn)行遷移后,就需要重新聯(lián)系服務(wù)提供者添加新的ip白名單。設(shè)置ip白名單的方式很多,除了傳統(tǒng)的防火墻之外,spring cloud alibaba提供的組件sentinel也支持白名單設(shè)置。為了降低api的復(fù)雜度,推薦使用防火墻規(guī)則進(jìn)行白名單設(shè)置。

          1.4 單個(gè)接口針對ip限流

          限流是為了更好的維護(hù)系統(tǒng)穩(wěn)定性。使用redis進(jìn)行接口調(diào)用次數(shù)統(tǒng)計(jì),ip+接口地址作為key,訪問次數(shù)作為value,每次請求value+1,設(shè)置過期時(shí)長來限制接口的調(diào)用頻率。

          1.5 記錄接口請求日志

          使用aop全局記錄請求日志,快速定位異常請求位置,排查問題原因。

          1.6 敏感數(shù)據(jù)脫敏

          在接口調(diào)用過程中,可能會(huì)涉及到訂單號(hào)等敏感數(shù)據(jù),這類數(shù)據(jù)通常需要脫敏處理,最常用的方式就是加密。加密方式使用安全性比較高的RSA非對稱加密。非對稱加密算法有兩個(gè)密鑰,這兩個(gè)密鑰完全不同但又完全匹配。只有使用匹配的一對公鑰和私鑰,才能完成對明文的加密和解密過程。

          二 冪等性問題

          冪等性是指任意多次請求的執(zhí)行結(jié)果和一次請求的執(zhí)行結(jié)果所產(chǎn)生的影響相同。說的直白一點(diǎn)就是查詢操作無論查詢多少次都不會(huì)影響數(shù)據(jù)本身,因此查詢操作本身就是冪等的。但是新增操作,每執(zhí)行一次數(shù)據(jù)庫就會(huì)發(fā)生變化,所以它是非冪等的。

          冪等問題的解決有很多思路,這里講一種比較嚴(yán)謹(jǐn)?shù)摹L峁┮粋€(gè)生成隨機(jī)數(shù)的接口,隨機(jī)數(shù)全局唯一。調(diào)用接口的時(shí)候帶入隨機(jī)數(shù)。第一次調(diào)用,業(yè)務(wù)處理成功后,將隨機(jī)數(shù)作為key,操作結(jié)果作為value,存入redis,同時(shí)設(shè)置過期時(shí)長。第二次調(diào)用,查詢r(jià)edis,如果key存在,則證明是重復(fù)提交,直接返回錯(cuò)誤。

          三 數(shù)據(jù)規(guī)范問題

          3.1 版本控制

          一套成熟的API文檔,一旦發(fā)布是不允許隨意修改接口的。這時(shí)候如果想新增或者修改接口,就需要加入版本控制,版本號(hào)可以是整數(shù)類型,也可以是浮點(diǎn)數(shù)類型。一般接口地址都會(huì)帶上版本號(hào),http://ip:port//v1/list。

          3.2 響應(yīng)狀態(tài)碼規(guī)范

          一個(gè)牛逼的API,還需要提供簡單明了的響應(yīng)值,根據(jù)狀態(tài)碼就可以大概知道問題所在。我們采用http的狀態(tài)碼進(jìn)行數(shù)據(jù)封裝,例如200表示請求成功,4xx表示客戶端錯(cuò)誤,5xx表示服務(wù)器內(nèi)部發(fā)生錯(cuò)誤。狀態(tài)碼設(shè)計(jì)參考如下:

          分類描述
          1xx信息,服務(wù)器收到請求,需要請求者繼續(xù)執(zhí)行操作
          2xx成功
          3xx重定向,需要進(jìn)一步的操作以完成請求
          4xx客戶端錯(cuò)誤,請求包含語法錯(cuò)誤或無法完成請求
          5xx服務(wù)端錯(cuò)誤

          狀態(tài)碼枚舉類:

          public?enum?CodeEnum?{

          ????//?根據(jù)業(yè)務(wù)需求進(jìn)行添加
          ????SUCCESS(200,"處理成功"),
          ????ERROR_PATH(404,"請求地址錯(cuò)誤"),
          ????ERROR_SERVER(505,"服務(wù)器內(nèi)部發(fā)生錯(cuò)誤");
          ????
          ????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 統(tǒng)一響應(yīng)數(shù)據(jù)格式

          為了方便給客戶端響應(yīng),響應(yīng)數(shù)據(jù)會(huì)包含三個(gè)屬性,狀態(tài)碼(code),信息描述(message),響應(yīng)數(shù)據(jù)(data)。客戶端根據(jù)狀態(tài)碼及信息描述可快速知道接口,如果狀態(tài)碼返回成功,再開始處理數(shù)據(jù)。

          響應(yīng)結(jié)果定義及常用方法:

          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;
          ????}

          ????/**
          ?????*?放入響應(yīng)枚舉
          ?????*/

          ????public?R?fillCode(CodeEnum?codeEnum){
          ????????this.setCode(codeEnum.getCode());
          ????????this.setMessage(codeEnum.getMessage());
          ????????return?this;
          ????}

          ????/**
          ?????*?放入響應(yīng)碼及信息
          ?????*/

          ????public?R?fillCode(int?code,?String?message){
          ????????this.setCode(code);
          ????????this.setMessage(message);
          ????????return?this;
          ????}

          ????/**
          ?????*?處理成功,放入自定義業(yè)務(wù)數(shù)據(jù)集合
          ?????*/

          ????public?R?fillData(Object?data)?{
          ????????this.setCode(CodeEnum.SUCCESS.getCode());
          ????????this.setMessage(CodeEnum.SUCCESS.getMessage());
          ????????this.data?=?data;
          ????????return?this;
          ????}
          }

          總結(jié)

          本篇文章從安全性、冪等性、數(shù)據(jù)規(guī)范等方面討論了API設(shè)計(jì)規(guī)范。除此之外,一個(gè)好的API還少不了一個(gè)優(yōu)秀的接口文檔。接口文檔的可讀性非常重要,雖然很多程序員都不喜歡寫文檔,而且不喜歡別人不寫文檔。為了不增加程序員的壓力,推薦使用swagger或其他接口管理工具,通過簡單配置,就可以在開發(fā)中測試接口的連通性,上線后也可以生成離線文檔用于管理API。


          < END >

          推薦閱讀:
          Java 15 正式發(fā)布, 好多新特性,刷新你的認(rèn)知!!
          2020年9月程序員工資最新統(tǒng)計(jì),以及中國編程語言9月排行榜!
          鍵盤敲入 A 字母時(shí),操作系統(tǒng)期間發(fā)生了什么...
          IDEA 上位?不!Eclipse Theia 1.0 發(fā)布!
          給 JDK 報(bào)了一個(gè) ?P4 的 Bug,結(jié)果居然……
          歡迎關(guān)注Java公眾號(hào)
          長按上圖,識(shí)別圖中二維碼即可關(guān)注
          瀏覽 62
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  亚洲视频,中文字幕 | 豆花视频免费在线观看无码 | 亚洲免费观看高清视频 | 国产精品一二二区 | 日韩黄色片网站 |