如何設計實現一個輕量的開放API閘道器.
前言
隨著業務的發展, 所對接的第三方越來越多, 各個業務系統面臨著同樣一個問題: 如何讓第三方安全快速接入
. 此時有一個集驗籤、鑑權、限流、降級等功能於一身的API閘道器服務變得尤為重要.
接下來將分享如何設計實現一個輕量級的API開放閘道器, 包括介面設計、資料庫設計、簽名驗籤方案、鑑權等. 本文側重於總體設計, 具體實現細節將陸續在後續的文章中分享.
API閘道器簡介
API閘道器在微服務中尤為重要, 其抽象了鑑權、限流、降級等各個業務系統通用的功能. 作為眾多內部業務系統外的一層屏障.
基本需求
- 簽名及驗籤
- 鑑權
- 路由
- 許可權及資源管理
總體設計
驗籤、鑑權等功能以職責鏈的方式進行處理, 閘道器根據配置進行路由並附加引數用以配合業務系統進行處理(如資料過濾等). 簡要請求處理流程如下:
介面設計
閘道器最基本的功能是轉發請求, 常見的方式是根據配置中的路由規則將請求轉發給內部服務, 如:
將/order/*
的請求轉發給內部的訂單系統、/user/*
的請求轉發給內部的使用者系統, 這種做法常用於對整個業務系統負責的基礎閘道器.
而本文所設計的是服務於第三方的開放API閘道器
, 並未使用上述做法, 而是將請求的資源作為引數放到請求體中, 其原因如下:
- 開放API服務於第三方, 遮蔽內部路徑, 有利於提供命名統一且規範的介面.
- 請求介面的對映由閘道器的路由表維護, 內部介面升級甚至切換到新服務對外介面不變.
- 能夠更細粒度地針對介面進行許可權控制、限流、統計等.
地址
開放API閘道器對外提供唯一入口, 具體請求的資源作為引數傳入.
公共引數
為了簡化簽名和驗籤的操作, 同時也提高靈活度, 唯一入口的約定了固定的公共引數和返回值, 如下:
公共請求引數
引數名稱 | 是否必須 | 型別 | 示例 | 備註 |
---|---|---|---|---|
app_id | 是 | string | 應用ID | |
method | 是 | string | aaa.bbb.ccc | 請求方法 |
charset | 是 | string | UTF-8 | 編碼 |
format | 是 | string | JSON | 業務引數格式 |
sign_type | 是 | string | RSA2 | 簽名型別 |
sign | 是 | string | 簽名 | |
timestamp | 是 | number | 1564929661796 | 時間戳, 單位: 毫秒 |
nonce | 是 | string | 63DCB93D270E44D49499F9E5D55705FE | 隨機字串(建議使用UUID) |
version | 是 | string | 1.0 | 介面版本 |
biz_content | 是 | string | {"start_time":"1564929661796", ...} | 請求業務引數 |
app_id
: 應用ID, 應用ID是授權的主體, 是呼叫方的身份標識method
: 請求方法, 與內部URL對應, 由閘道器的路由表維護.timestamp
和nonce
用來防重放攻擊.biz_content
: 業務引數, 這個引數將轉發給內部業務系統.
公共返回引數
引數名稱 | 是否必須 | 型別 | 示例 | 備註 |
---|---|---|---|---|
code | 是 | number | 0 | 錯誤碼 |
message | 否 | string | 錯誤資訊 | |
charset | 是 | string | UTF-8 | 編碼 |
format | 是 | string | JSON | 返回引數格式 |
sign_type | 是 | string | RSA2 | 簽名型別 |
sign | 是 | string | 簽名 | |
timestamp | 是 | number | 時間戳, 單位: 毫秒 | |
biz_content | 是 | string | {"id":"1564929661796", ...} | 返回業務引數 |
biz_content
: 返回業務引數, 閘道器轉發業務系統的返回值.
本文釋出於樸瑞卿的部落格, 允許非商業用途轉載, 但轉載必須保留原作者樸瑞卿 及連結:blog.piaoruiqing.com. 如有授權方面的協商或合作, 請聯絡郵箱: piaoruiqing@gmail.com.
簽名方案
呼叫方和服務方均生成2048
位RSA
祕鑰, 交換公鑰. 私鑰用於簽名, 公鑰用於驗籤, 開放API閘道器對外介面使用https
, 故暫不需額外做加密處理.
簽名演算法
簽名演算法名稱 | 標準簽名演算法名稱 | 備註 |
---|---|---|
RSA2 | SHA256WithRSA | 強制要求 RSA 金鑰的長度至少為 2048 |
簽名規則
簽名引數內容
剔除sign
之後的全部引數.
簽名引數排序
按照引數名的ASCII
碼遞增排序(字母升序排序).
簽名生成方式
排序後的引數列表組合成引數名a=引數值a&引數名b=引數值b&...&引數名z=引數值z
的字串, 並使用私鑰
生成sign
.
資料庫設計
資料庫用於儲存祕鑰許可權等配置, 程式和資料庫之間有多級快取用以提高訪問速度. 簡要ER圖如下:
app
: 呼叫方主體, 用於標識請求方身份.group
: 組,app
分組, 可通過group
統一進行授權.subject
: 主體(app/group).resource
: 資源, 維護請求資源與內部介面的對映關係,url
+http_method
對應唯一的resource_id.
技術選型
閘道器除了滿足功能上的需求外, 效能上的需求也需要著重考慮, 畢竟作為各個業務系統對外的唯一入口, 閘道器的效能可能會成為整個業務系統的瓶頸. 業務並不複雜, 效能要求高, 響應式程式設計正是一個不錯的選擇.
Spring WebFlux
+netty
: 響應式Web框架.Spring Data Reactive Redis
+Lettuce
: 響應式redis客戶端.Guava
: Google工具包, 使用LoadingCache
作為程式內快取.
結語
閘道器作為內部系統外面的一層屏障和入口, 除基本功能和效能上的需求外, 監控、統計、日誌等都是需要考慮到的問題, 閘道器方面開源產品眾多, 但選擇時一定要考慮自身業務, 適合自身的前提下參考各個成熟的方案進行實踐.
如果這篇文章對您有幫助,請點個贊吧 ( ̄▽ ̄)"
系列文章:
歡迎關注公眾號:
本文釋出於樸瑞卿的部落格, 允許非商業用途轉載, 但轉載必須保留原作者樸瑞卿 及連結:blog.piaoruiqing.com. 如有授權方面的協商或合作, 請聯絡郵箱: piaoruiqing@gmail.com.