首頁  >  文章  >  後端開發  >  設計API介面時,要注意這些地方!

設計API介面時,要注意這些地方!

藏色散人
藏色散人轉載
2023-01-09 11:10:241662瀏覽

本篇文章為大家帶來了關於API的相關知識,其中主要介紹了設計API需要注意哪些地方?怎麼設計一個優雅的API接口,有興趣的朋友,下面一起來看吧,希望對大家有幫助。

前言

在實際工作中,我們需要經常跟第三方平台打交道,可能會對接第三方平台API接口,或者提供API接口給第三方平台調用。

那麼問題來了,如果設計一個優雅的API接口,能夠滿足:安全性、可重複呼叫、穩定性、好定位問題等多面向需求?

今天跟大家一起聊聊設計API介面時,需要注意的一些地方,希望對你會有所幫助。

1. 簽章

為了防止API介面中的資料被竄改,很多時候我們需要對API介面做簽章

介面請求方將請求參數 時間戳 密鑰拼接成一個字串,然後透過md5等hash演算法,產生一個前面sign。

然後在請求參數或請求頭中,增加sign參數,傳遞給API介面。

API介面的閘道服務,取得到該sign值,然後用相同的請求參數時間戳密鑰拼接成一個字串,用相同的m5演算法產生另外一個sign,對比兩個sign值是否相等。

如果兩個sign相等,則認為是有效請求,API介面的網關服務會將給請求轉送給對應的業務系統。

如果兩個sign不相等,則API介面的網關服務會直接傳回簽章錯誤。

問題來了:簽名中為什麼要加時間戳記?

答:為了安全性考慮,防止同一次請求被反覆利用,增加了密鑰沒破解的可能性,我們必須要對每次請求都設定一個合理的過期時間,例如:15分鐘。

這樣一次請求,在15分鐘內是有效的,超過15分鐘,API介面的網關服務會傳回超過有效期限的例外狀況提示。

目前產生簽章中的金鑰有兩種形式:

一種是雙方約定一個固定值privateKey。

另一種是API介面提供者給予AK/SK兩個值,雙方約定用SK作為簽章中的金鑰。 AK介面呼叫方作為header中的accessKey傳遞給API介面提供方,這樣API介面提供者可以根據AK取得到SK,而產生新的sgin。

2. 加密

有些時候,我們的API介面直接傳遞的非常重要的數據,例如:用戶的銀行卡號、轉帳金額、用戶身分證等,如果將這些參數,直接明文,暴露到公網上是非常危險的事。

由此,我們需要對資料進行加密

目前使用比較多的是用BASE64加解密。

我們可以將所有的數據,安裝一定的規律拼接成一個大的字串,然後在加一個密鑰,拼接到一起。

接著使用JDK1.8之後的Base64工具類別處理,效果如下:

【加密前的数据】www.baidu.com
【加密后的数据】d3d3LmJhaWR1LmNvbQ==复制代码

為了安全性,使用Base64可以加密多次。

API介面的呼叫方在傳遞參數時,body中只有一個參數data,它就是base64之後的加密資料。

API介面的閘道服務,在接收到data資料後,根據雙方事先預定的金鑰、加密演算法、加密次數等,進行解密,並且反序列化出參數資料。

3. ip白名單

為了進一步加強API介面的安全性,防止介面的簽章或加密被破解了,攻擊者可以在自己的伺服器上請求該介面。

需求限制請求ip,增加ip白名單

只有在白名單中的ip位址,才能成功請求API接口,否則直接傳回無存取權限。

ip白名單也可以加在API網關服務上。

但也要防止公司的內部應用伺服器被攻破,這種情況也可以從內部伺服器發起API介面的請求。

這時候就需要增加web防火牆了,例如:ModSecurity等。

4. 限流

如果你的API介面被第三方平台呼叫了,這就意味著著,呼叫頻率是沒辦法控制的。

第三方平台呼叫你的API介面時,如果並發量一下子太高,可能會導致你的API服務不可用,介面直接掛掉。

由此,必須要對API介面做限流

限流方法有三種:

  • 對請求ip做限流:例如同一個ip,在一分鐘內,對API介面總的請求次數,不能超過10000次。

  • 對請求介面做限流:例如同一個ip,在一分鐘內,對指定的API介面,請求次數不能超過2000次。

  • 對請求用戶做限流:例如同一個AK/SK用戶,在一分鐘內,對API介面總的請求次數,不能超過10000次。

我们在实际工作中,可以通过nginxredis或者gateway实现限流的功能。

5. 参数校验

我们需要对API接口做参数校验,比如:校验必填字段是否为空,校验字段类型,校验字段长度,校验枚举值等等。

这样做可以拦截一些无效的请求。

比如在新增数据时,字段长度超过了数据字段的最大长度,数据库会直接报错。

但这种异常的请求,我们完全可以在API接口的前期进行识别,没有必要走到数据库保存数据那一步,浪费系统资源。

有些金额字段,本来是正数,但如果用户传入了负数,万一接口没做校验,可能会导致一些没必要的损失。

还有些状态字段,如果不做校验,用户如果传入了系统中不存在的枚举值,就会导致保存的数据异常。

由此可见,做参数校验是非常有必要的。

在Java中校验数据使用最多的是hiberateValidator框架,它里面包含了@Null、@NotEmpty、@Size、@Max、@Min等注解。

用它们校验数据非常方便。

当然有些日期字段和枚举字段,可能需要通过自定义注解的方式实现参数校验。

6. 统一返回值

我之前调用过别人的API接口,正常返回数据是一种json格式,比如:

{    
"code":0,    
"message":null,    
"data":[{"id":123,"name":"abc"}]
},

签名错误返回的json格式:

{    
"code":1001,    
"message":"签名错误",    
"data":null
}

没有数据权限返回的json格式:

{
    "rt":10,
    "errorMgt":"没有权限",
    "result":null
    }

这种是比较坑的做法,返回值中有多种不同格式的返回数据,这样会导致对接方很难理解。

出现这种情况,可能是API网关定义了一直返回值结构,业务系统定义了另外一种返回值结构。如果是网关异常,则返回网关定义的返回值结构,如果是业务系统异常,则返回业务系统的返回值结构。

但这样会导致API接口出现不同的异常时,返回不同的返回值结构,非常不利于接口的维护。

其实这个问题我们可以在设计API网关时解决。

业务系统在出现异常时,抛出业务异常的RuntimeException,其中有个message字段定义异常信息。

所有的API接口都必须经过API网关,API网关捕获该业务异常,然后转换成统一的异常结构返回,这样能统一返回值结构。

7. 统一封装异常

我们的API接口需要对异常进行统一处理。

不知道你有没有遇到过这种场景:有时候在API接口中,需要访问数据库,但表不存在,或者sql语句异常,就会直接把sql信息在API接口中直接返回。

返回值中包含了异常堆栈信息数据库信息错误代码和行数等信息。

如果直接把这些内容暴露给第三方平台,是很危险的事情。

有些不法分子,利用接口返回值中的这些信息,有可能会进行sql注入或者直接脱库,而对我们系统造成一定的损失。

因此非常有必要对API接口中的异常做统一处理,把异常转换成这样:

{    
"code":500,    
"message":"服务器内部错误",    
"data":null
}

返回码code500,返回信息message服务器内部异常

这样第三方平台就知道是API接口出现了内部问题,但不知道具体原因,他们可以找我们排查问题。

我们可以在内部的日志文件中,把堆栈信息、数据库信息、错误代码行数等信息,打印出来。

我们可以在gateway中对异常进行拦截,做统一封装,然后给第三方平台的是处理后没有敏感信息的错误信息。

8. 请求日志

在第三方平台请求你的API接口时,接口的请求日志非常重要,通过它可以快速的分析和定位问题。

我们需要把API接口的请求url、请求参数、请求头、请求方式、响应数据和响应时间等,记录到日志文件中。

最好有traceId,可以通过它串联整个请求的日志,过滤多余的日志。

当然有些时候,请求日志不光是你们公司开发人员需要查看,第三方平台的用户也需要能查看接口的请求日志。

这时就需要把日志落地到数据库,比如:mongodb或者elastic search,然后做一个UI页面,给第三方平台的用户开通查看权限。这样他们就能在外网查看请求日志了,他们自己也能定位一部分问题。

9. 冪等設計

第三方平台極有可能在極短的時間內,請求我們介面多次,例如:在1秒內請求兩次。有可能是他們業務系統有bug,或是在做介面呼叫失敗重試,因此我們的API介面需要做冪等設計

也就是說要支援在極短的時間內,第三方平台用相同的參數請求API介面多次,第一次請求資料庫會新增數據,但第二次請求以後就不會新增數據,但也會回傳成功。

這樣做的目的是不會產生錯誤資料。

我們在日常工作中,可以透過在資料庫中增加唯一索引,或是在redis儲存requestId和請求參來保證接口冪等性。

對介面冪等性感興趣的小夥伴,可以看看我的另一篇文章《高並發下如何保證介面的冪等性? 》,裡面有非常詳細的介紹。

10. 限制記錄條數

對於對我提供的批次接口,一定要限制請求的記錄條數

如果要求的資料太多,很容易造成API介面逾時等問題,讓API介面變得不穩定。

通常情況下,建議一次請求中的參數,最多支援傳入500筆記錄。

如果使用者傳入多餘500筆記錄,則介面直接給予提示。

建議這個參數做成可設定的,並且事先要跟第三方平台協商好,避免上線後產生不必要的問題。

11. 壓測

上線前我們務必對API介面做一下壓力測試,知道各個介面的qps情況。

以便於我們能夠更好的預估,需要部署多少伺服器節點,對於API介面的穩定性至關重要。

之前雖說對API介面做了限流,但是實際上API介面是否能夠達到限制的閥值,這是一個問號,如果不做壓力測試,是有很大風險的。

例如:你API介面限流1秒只允許50次請求,但實際API介面只能處理30次請求,這樣你的API介面也會處理不過來。

我們在工作中可以用jmeterapache benc對API介面做壓力測試。

12. 非同步處理

一般的API介面的邏輯都是同步處理的,請求完後立刻回傳結果。

但有時候,我們的API接口裡面的業務邏輯非常複雜,特別是有些批量接口,如果同步處理業務,耗時會非常長。

這種情況下,為了提升API介面的效能,我們可以改成非同步處理

在API介面中可以傳送一則mq訊息,然後直接回傳成功。之後,有個專門的mq消費者去非同步消費該訊息,做業務邏輯處理。

直接非同步處理的接口,第三方平台有兩種方式取得到。

第一種方式是:我們回呼第三方平台的接口,告知他們API接口的處理結果,很多支付接口就是這麼玩的。

第二種方式是:第三方平台透過輪詢呼叫我們另外一個查詢狀態的API接口,每隔一段時間查詢一次狀態,傳入的參數是之前的那個API介面中的id集合。

13. 資料脫敏

有時候第三方平台呼叫我們API介面時,取得的資料中有一部分是敏感數據,例如:使用者手機號碼、銀行卡號等等。

這樣資訊如果透過API介面直接保留到外網,是非常不安全的,很容易造成用戶隱私資料外洩的問題。

這就需要對部分資料做資料脫敏了。

我們可以在傳回的資料中,部分內容用星號取代。

已用戶手機號碼為例:182****887

這樣即使資料外洩了,也只洩漏了一部分,不法份子拿到這份資料也沒啥用。

14. 完整的介面文檔

說實話,一份完整的API介面文檔,在雙方做介面對接時,可以減少很多溝通成本,讓對方少走很多彎路。

介面文件中需要包含以下資訊:

  • 介面位址

  • 要求方式,例如:post或get

  • 請求參數和欄位介紹

  • 傳回值和欄位介紹

  • 傳回碼與錯誤訊息

  • 加密或簽章範例

  • 完整的請求demo

  • 額外的說明,例如:開通ip白名單。

介面文件中最好能夠統一介面和欄位名稱的命名風格,例如都用駝峰標識命名。

統一欄位的類型和長度,例如:id欄位用Long類型,長度規定20。 status欄位用int型,長度固定2等。

統一時間格式字段,例如:time用String類型,格式為:yyyy-MM-dd HH:mm:ss。

介面文件中寫明AK/SK和域名,找某某單獨提供等。

推薦學習:《PHP影片教學

#

以上是設計API介面時,要注意這些地方!的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.im。如有侵權,請聯絡admin@php.cn刪除