- API安全技術與實戰
- 錢君生 楊明 韋巍編著
- 3834字
- 2021-07-08 11:51:08
1.3 現代API常用的協議和消息格式
現代API技術的發展要追溯到23000年,在動態網頁技術的推動下,大量的企業級應用如雨后春筍般涌現,為了滿足不同技術棧構建的應用在架構和開發上能平滑融合和解耦,API技術也得到了快速的發展。
1.3.1 REST成熟度模型
現代API的奠基人Roy Fielding博士在他的論文《架構風格以及基于網絡的軟件架構設計》(Architectural Styles and the Design of Network-based Software Architectures)中第一次提到REST(Representational State Transfer)概念,其目的是滿足現代Web架構的設計與開發的需要;之后,Leonard Richardson提出“REST成熟度模型”,該模型把REST服務按照成熟度劃分成4個層次。
■ Level 0:Web服務使用HTTP協議作為傳輸方式,實際上是遠程過程調用(Remote Procedure Call,RPC)的雛形,SOAP和XML-RPC都屬于此類,其表現形式為一個URI,一個HTTP方法。例如:

■ Level 1:Web服務引入了資源的概念,每個資源有對應的標識符和表述。其表現形式為多個URI,一個HTTP方法。例如:

■ Level 2:Web服務使用不同的HTTP方法來進行不同的操作,并且使用HTTP狀態碼來表示不同的結果。如HTTP GET方法來獲取資源,HTTP DELETE方法來刪除資源,這是當前使用范圍最為廣泛的層次。其表現形式為多個URI,多個HTTP方法。例如:

■ Level 3:Web服務使用HATEOAS,在資源的表述中包含了鏈接信息,客戶端可以根據鏈接來發現可以執行的動作。Level 3是比較理想的層級,但目前實際應用較少。
從“REST成熟度模型”中各個層次的含義來看,目前大多數應用基本都停留在Level 1、Level 2的層次,所以在后續討論RESTful API的章節中,主要是指Level 1、Level 2兩個層次。
1.3.2 RESTful API技術
在當前的互聯網上,因RESTful API簡潔易用,在降低軟件開發復雜度的同時,也提高了軟件應用的拓展性,從而占據著主流地位。從REST成熟度模型來看,表現形式以Level 2為主,一次RESTful API請求,其典型的消息格式樣例如下:

在樣例中,包含以下RESTful API相關的協議信息。
■ 資源URL格式為schema://host[:port]/version/path,其中schema是指定使用的應用層協議,比如HTTP、HTTPS、FTP等;host是API服務器的IP地址或域名;port是指API服務器的端口;version是指API請求的版本;path是指API請求資源的路徑。
■ 資源請求分配的HTTP請求方法,除了樣例中的GET方法外,常用的請求方法還有用于服務器新增數據或資源的POST方法,用于獲取資源請求的元數據HEAD方法,用于更新服務器資源的PUT方法,用于刪除服務器資源的DELETE方法以及查詢與資源相關選項的OPTIONS方法等。不同HTTP請求方法的調用樣例如下:

在實際應用中,對于API請求路徑的命名通常遵循一定的規范或規律,比如將功能相近的API端點放在一起:

通過這些接口規范性的特征,讀者很容易識別出RESTful API類的接口。而作為技術開發者,為了滿足這些接口標準,一般采用業界通用API規范。在現行的API規范中,OpenAPI當之無愧排在首位,其官網地址為https://swagger.io/specification/。從其官方文檔可以了解到,OpenAPI規范于2015年已捐贈給Linux基金會,其規范內容為RESTful API定義了一個與開發語言無關的標準接口,可通過有效映射與之關聯的所有資源和操作,來幫助用戶輕松地開發和使用RESTful API。OpenAPI規范中描述REST風格通信消息所采用的MIME類型以JSON格式為主,如圖1-10所示。

●圖1-10 REST采用的MIME類型
同時,在規范中,關于身份認證與鑒權的安全性支持方案,如APIKey、HTTP Basic、OAuth 2.0等也做出了相應的描述,在后續的API安全設計章節中將為讀者做詳細的介紹。
1.3.3 GraphQL API技術
GraphQL是Facebook推出的一種基于用戶自定義數據類型的API查詢語言和現代應用程序對接云服務的全面解決方案,在很多場景下,可以作為REST、SOAP或gRPC的替代方案。
一個典型的GraphQL服務是通過定義類型、類型上的字段、字段的解析函數來對外部提供能力服務的。這里,以用戶admin的查詢為樣例,描述其交互過程。當請求GraphQL服務時,其查詢結構為:


這不是JSON格式的數據,但它們很相似,此GraphQL查詢的表達含義如下。
■ 通過用戶名admin來查詢用戶信息。
■ 僅查詢id、name、address三個字段的信息。
■ 對于通信地址address,需要查詢首選地址和備用地址。
而與之對應的服務器響應為:

這個響應的消息結構顯示了GraphQL的兩個重要的特性。
■ 服務器能理解客戶端的要求并根據定義的模式完成查詢和響應,這種特性能幫助使用者從技術路線層面解決OWASP API安全中的批量分配問題。而在業務層面,使后端服務的開發人員更多的關注開發,而不用關心業務數據的接口,由前端查詢來控制其想獲取的字段。
■ 可以嵌套地訪問數據資源,在RESTful API如果想查詢用戶上述信息,則對應的API端點為/v1/user和/v1/user/address,而GraphQL API則一次性完成。這在大型的互聯網應用中,可以減少時間成本的消耗。
也正是GraphQL的這些特性,當技術人員嘗試使用它時,也有諸多的不便。舉例如下。
■ GraphQL語言自身特有的查詢語法需要投入學習成本,且其結構沒有JSON直觀,在編寫過程中需要特定的輔助工具。
■ 為了適應其嵌套查詢的特性,需要定義大量的schema,并進行服務器端改造。
■ 嵌套查詢對普通關系型數據的服務器性能挑戰較大。
1.3.4 SOAP API技術
SOAP API相對于其他的API技術來說,已進入了衰退期,但在企業級應用中,因歷史遺留問題仍在普遍使用著。通俗地說,SOAP協議是基于HTTP協議的XML通信技術,主要用于Web Service服務通信。在技術實現上,一個完整的SOAP API由3部分組成:SOAP(簡單對象訪問協議)、UDDI(Web Services提供信息注冊中心的實現標準規范)、WSDL(描述Web Services以及如何對它們進行訪問),它們之間的相互關系如圖1-11所示。

●圖1-11 SOAP API技術的組成
WSDL為服務消費者提供了Web Services接口的詳細描述,通過解析WSDL獲取調用參數的詳細描述后,使用XML格式的數據與服務提供者進行數據交互。
一個典型的SOAP消息,其基本格式如下所示:

其中Envelope和Body為必選節點,Envelope用于標識此消息為SOAP消息,Body包含所有調用和響應的必須信息。這里,通過獲取API版本的SOAP消息請求與響應來讓讀者對SOAP消息有更理性的認識,如下所示。
SOAP請求:用于請求API的版本信息,當獲取的API名稱為test的API版本時,發送的SOAP消息樣例。其中m:GetApiVersion和m:ApiName是應用程序業務專用的自定義節點。代碼如下所示:


SOAP響應:服務器端對獲取API版本信息的響應報文樣例,其中m:Version表示版本信息為2.5.0版本。代碼如下所示:

1.3.5 gRPC API技術
gRPC是一套高性能、開源的遠程調用框架,通過Server/Client模式,使得通信中的各個應用之間像調用本地接口一樣調用遠程API。在其官網中,對于為什么要使用gPRC有如下描述。
gRPC是可以在任何環境中運行的現代開源高性能RPC框架,它可以通過可插拔方式,有效地支撐數據中心內和跨數據中心的服務連接,以實現負載平衡、跟蹤、運行狀況檢查和身份驗證。它同樣也適用于分布式計算的“最后一公里”,以將設備、移動應用程序和瀏覽器連接到后端服務。
在gRPC API中,客戶端應用程序通過遠程方法調用在其他服務器的應用程序,多個RPC系統之間,圍繞API服務的思想,通過協議約定接口參數和返回類型,完成不同服務能力的組合。不同的客戶端或服務器端之間,無須考慮編程語言的不同,均參照協議約定遠程調用接口,如圖1-12所示。

●圖1-12 gRPC通信
在客戶端與服務器端之間,將數據(比如JSON格式數據)序列化為二進制編碼,然后使用Protobuf協議進行通信。gRPC API通常適用于對接口安全性或性能要求較高的場景,比如某個具備管理功能屬性的接口,想通過嚴格的gRPC API約束其調用者的范圍,則Protobuf協議恰好滿足此需求。
Protobuf協議的消息結構是通過Protocol Buffer Language語言進行定義和描述的,其數據結構描述文件的拓展名是.proto,其樣例結構如下:

在使用時,需要先將.proto的文件編譯,再序列化,才能在通信中使用。讀者可以將其理解為:客戶端和服務器端通信時,先將JSON或XML格式的數據使用Protobuf技術轉換為二進制流的數據格式,再進行傳輸。
在表現形式上,gRPC API比RESTful API相對來說具有更好的隱蔽性,同時gRPC API的技術實現中也支持多種安全機制,比如通信鏈路的SSL/TLS安全協議、X.509數字證書的認證、OAuth協議授權訪問、Google令牌認證等。
1.3.6 類XML-RPC及其他API技術
類XML-RPC及其他API技術比較雜亂,以類XML-RPC技術為主,它除了包含XML-RPC的API接口調用外,還有一些以XML為數據格式的信息交換技術,如即時通信的XMPP,在這里,也將這類的接口都歸類到類XML-RPC API中。另外,還有一些如JMS、Dubbo之類的接口技術,也歸類到這里,做統一的敘述。
下面,一起來看看類XML-RPC API。
XML-RPC是一種簡單、古老的遠程接口調用方法,使用HTTP將信息在客戶端和服務器端之間傳輸。從通信的消息格式上看,與其他的API技術典型的差異在于消息體的XML文檔化,如下面樣例所示。
類XML-RPC請求:在請求消息中,所有的節點包含在methodCall中,其中methodName節點表示調用的方法名,param節點表示調用時使用的參數類型及其參數值。比如此樣例中,請求調用的方法為testRPC,調用時參數值為2:

類XML-RPC響應:在響應消息中,所有的節點包含methodResponse中,其中param節點為正確響應的內容。比如此樣例中,響應消息的值為字符串類型的admin:

從樣例可以看出,變化的主要內容是通信交互的消息體,還有一點需要注意的是,對于遠程接口中某個方法的調用,是在消息體中定義的,比如樣例中調用遠程接口的testRPC方法包含在XML格式中,而不是像普通的HTTP請求,放在URL路徑中。除了上述差異,其他(如HTTP Header相關字段)與普通HTTP消息無異,調用堆棧與1.2.1節描述的RMI無異,更多差異化的細節體現在后端服務的邏輯實現上。
JMS作為Java消息服務類應用程序接口在大型企業級項目中也被頻繁使用,市場上也有多種具體的產品實現,比如ActiveMQ、Kafka、Rabbit MQ等。與XML-RPC類不同,JMS的組成結構相對復雜些,如圖1-13所示。

●圖1-13 JMS通信過程
JMS主要用于兩個應用程序之間或分布式系統中發送消息,進行同步或異步通信。消息發布者產生消息,并將消息發布到消息隊列或對外發布主題Topic。在P2P模式下,每條消息僅會傳送給一個消費者;而在發布/訂閱模式下,每條消息會發送給訂閱的多個消息消費者。JMS消息作為通信內容的載體,其結構主要分為消息頭、屬性和消息體三個部分。根據消息類型的不同,常用的主要有TextMessage文本消息、MapMessage鍵值對消息、BytesMessage二進制數據格式消息、ObjectMessage Java序列化對象消息以及StreamMessage以XML為傳輸載體的流消息。
通過理解JMS、XML-RPC的消息傳輸,能幫助讀者快速理解Dubbo、XMPP等類型接口的技術原理,這也是將其他的API技術歸類到此類型的另一個原因。