摘" 要:随着微服务架构的普及,API网关作为连接前端与后端服务的关键中间层,承担着访问控制、身份验证等多项安全职责。为了解决在网关层面对响应数据进行细粒度访问控制的问题,设计一种支持属性授权的API网关架构,并提出一种基于流式解析的属性授权控制策略。在网关启动阶段构建基于抽象语法树的路径匹配器,在运行阶段渐进式解析请求响应。实验证明,该方法相比现有方式未明显提升CPU负载,在内存占用和响应时间方面均有明显优势。
关键词:API网关;数据保护;属性授权;流式解析
中图分类号:TP391.4;TN929.5 文献标识码:A 文章编号:2096-4706(2024)11-0026-06
Research on API Gateway Attribute Authorization Strategy under Microservice Architecture
ZHANG Liqing
(Shanghai Economic Information Center, Shanghai" 200050, China)
Abstract: With the popularization of microservice architecture, API gateway serves as a key intermediate layer connecting front-end and back-end services, undertaking multiple security responsibilities such as access control and identity verification. To address the issue of fine-grained access control for response data at the gateway layer, an API gateway architecture that supports attribute authorization is designed, and an attribute authorization control strategy based on streaming parsing is proposed. It builds a path matcher based on an abstract syntax tree during the gateway startup phase, and gradually parses request responses during the runtime phase. Experimental results show that this method does not significantly improve CPU load compared to existing methods, and has significant advantages in memory usage and response time.
Keywords: API Gateway; data protection; attribute authorization; streaming parsing
0" 引" 言
在当代软件开发实践中,微服务架构[1]已成为一种主流的设计范式,其被广泛应用于构建可扩展、灵活且独立部署的系统。在微服务架构中,API网关扮演着至关重要的角色,它不仅是客户端与微服务系统之间的中介,还负责请求路由、身份验证、协议转换、负载平衡、缓存管理等多种功能[2],如图1所示。API网关的设计原则和实现对于维护微服务架构的可扩展性、灵活性和安全性至关重要。API网关作为微服务架构的入口点,有助于简化客户端与各个微服务之间的交互。通过在网关层上实施跨服务的功能,如身份验证和授权、日志记录、监控和警报,可以减少各个微服务中的重复代码,从而简化微服务的开发和维护工作。此外,API网关可以对外部请求进行预处理和对内部响应进行后处理,实现路由请求、格式转换和协议转换,从而为客户端提供无缝的API接口[3]。
确保调用方在API层面具备合法授权是确保服务安全的基础,通常通过OAuth 2.0 [4]、JWT [5]等标准协议实现。这种授权机制有效地防止了未授权访问,但通常仅限于接口级别,而不细化到接口响应中的特定属性。在API网关层面实施对响应中特定属性的细粒度授权管理,在生产实践中具有重要意义。它可以解决以下问题:
1)数据过滤与隐私保护。通过对响应数据中的特定属性实施细粒度控制,可以根据不同用户的权限动态过滤响应数据,仅展示用户被授权查看的数据。这对于多租户环境、个人数据保护法[6,7]规遵循尤为重要。
2)减少客户端处理负担。在服务端进行数据过滤,减少了发送到客户端的数据量,客户端不需要编写额外的逻辑来处理不应该显示的数据,减轻了客户端的处理负担,优化了用户体验。
3)提高系统安全性。在某些场景下,即使用户可以访问某个接口,也可能不应该查看到接口返回的所有数据。例如,一个用户可能有权查看一个列表接口,但列表中的某些项或某些详情可能涉及更高级别的权限。通过细粒度控制,可以更精确地实施安全策略。
Archana等[8]提出了一种基于树的属性授权控制策略,将消息响应全量解析为JSONTree,然后依据属性授权配置对其进行修剪,得到期望的响应结构。这种全量解析响应消息体的方式会显著增加网关负载,尤其是在高并发场景下,将会影响系统整体性能。因此,本文提出了一种基于流式解析的属性授权策略,对响应结果进行渐进式解析,并同步构建目标结构。
1" 网关原型设计
1.1" 数据交换格式及配置语言介绍
在微服务架构的信息交换领域,JavaScript对象表示法(JSON)与可扩展标记语言(XML)已普遍被采纳为事实上的标准数据格式。属性授权机制负责解析供应方返回的JSON或XML格式响应,进而施行筛选规则,确保只有得到授权的数据属性被允许传递。本研究中,将JSON作为微服务API的默认响应格式。
JSONPath [9]表达式是一种查询语言,用于从JSON文档中提取数据,类似于XML的XPath。通过JSONPath,可以方便地定位和提取JSON文档中的数据,无论是单个元素还是一组元素。JSONPath提供了丰富的表达式,可以用来执行复杂的查询,比如筛选、迭代以及找到特定的数据项。表1列举出了JSONPath的基本语法,例如可以使用$.store.book[*].author表示获取商店中所有书的作者名称。
1.2" 网关原型架构
本文参考已有网关模式[10,11],设计了支持属性授权的API网关系统架构的3个主要模块,分别是加载器(Loader)、路径构建器(Path Builder)以及一个具有流式解析功能的响应处理器(Response Handler),架构原型如图2所示。
图2" API网关架构原型
服务根据实际业务需求,提供方决定客户端有权访问的接口以及具体数据属性。这些信息以JSON文档的形式存储在数据源中,每条记录定义了指定客户端被授权属性的JSONPath表达式。例如,在一个获取用户教育信息的场景里,以下配置表示ID为123的客户端在对服务接口/api/lookup/{id}的GET调用中,可以读取到该用户所有就读经历中的学校名称、专业和开始时间。实现代码如下:
{
\"client Id\":" "\"123\",
\"method\":" "\"GET\",
\"path\":" "\"/api/lookup/education/{id}\",
\"authorizedAttributes\":" "[
\"$. education. schools[*]. name\",
\"$. education. schools[*]. major\",
\"$. education. schools[*].stime\"
]
}
在网关启动时,将执行以下两个步骤:
1)加载器从数据源读取授权记录并将其提供给路径构建器。
2)路径构建器为每一条授权记录构建一个索引,该索引将客户端映射到被授权的API列表以及这些API的属性列表。
当客户端发起API调用时,网关拦截请求并将其路由到服务提供方。服务提供方处理请求并将响应发送回API网关。在API网关内部,自定义响应处理器拦截响应并调用相应的路径匹配器,渐进式的解析响应数据,并构造目标结构。
2" 基于抽象语法树的路径匹配器构建
在系统启动阶段,加载器模块从数据源中检索服务提供方提供的授权信息,其输出为表示客户端针对特定API端点被授权属性的JSON文档列表。加载器在配置的时间间隔内定期刷新,这有助于应对动态客户端授权变化。路径构建器接收加载器模块的输出,并将每条记录添加到一个内存索引中。该索引将客户端映射到被授权的请求URI列表以及与这些URI关联的被授权属性。索引的内容如表2表示。
同时,属性授权配置中包含的JSONPath表达式被预编译成路径匹配器。这个预编译过程包括解析每个JSONPath表达式,构建对应的抽象语法树(Abstract Syntax Tree, AST)[12],然后根据AST构建路径匹配器。相比于运行时解析表达式文本,基于AST的路径匹配器可以更快地执行,因为许多复杂的解析工作已经在预编译阶段完成。此外,AST可以支持复杂的查询优化,如预计算常量表达式、重用共同的表达式子树等,因此这些匹配器在运行时可以更快速地判断响应JSON中的哪些属性与给定的JSONPath表达式相匹配。其过程如下:
构建路径匹配器集合算法:
输入:JSONPath表达式集合configRules
输出:路径匹配器集合pathMatchers
1. function BuildPathMatchers(configRules)
2." "初始化空的路径匹配器集合pathMatchers
3." "for每个表达式expr ∈ configRules , do
4." " " "AST ← BuildAST 解析表达式expr为抽象语法树
5." " " "matcher ← BuildMatcher 构建基于AST的路径匹配器
6." " " "将matcher添加到pathMatchers集合中
7." "end for
8." "返回pathMatchers
基于JSONPath的抽象语法树构造算法:
输入:JSONPath表达式expr
输出:抽象语法树AST
1.function BuildAST(expr)
2." "初始化空的栈stack和当前节点currentNode
3." "for expr中的每个字符c, do
4." " " "根据c的类型更新stack和currentNode
5." " " "构建AST的相应部分
6." "end for
7." "当stack非空时,将栈顶节点出栈,完成AST构建
8." "返回AST
基于AST的路径匹配器构造算法:
输入:抽象语法树AST
输出:路径匹配器matcher
1.function BuildMatcher(AST)
2." 根据AST的结构初始化matcher
3." for AST的每个节点node, do
4." " " 根据node的类型和值,向matcher添加匹配逻辑
5." " " 对于复合节点,递归添加其子节点的匹配逻辑
6." "end for
7." "返回初始化并配置好的matcher
上述算法伪代码分为两个主要部分:
1)预编译过程,它将JSONPath表达式集合转换为路径匹配器集合,每个匹配器都基于一个表达式的抽象语法树(AST)构建。
2)提供了两个辅助函数:“解析表达式为抽象语法树”和“构建基于AST的路径匹配器”,分别用于解析JSONPath表达式成AST和根据AST构建路径匹配器。
3" 基于流式解析的属性授权策略
网关的响应处理器负责过滤原始响应,流程包含检索与构建两个阶段。检索阶段,处理器根据传入的请求构建索引查找键,该键是一个包含clientId和方法类型的JSON文本。例如,对于来自ID为123的客户端,传入请求GET/api/lookup/abc,则其查找键可以表示为:clientId=123,method=GET。接下来,该模块使用查找键在索引中进行查找,以检索客户端对应的属性授权策略值。由于值本身也是一个映射,检索器随后遍历映射的所有键,以找到与传入请求URI匹配的键。本文使用模板匹配法来识别与传入请求URI相对应的键,对应于键的值即是被授权的属性列表。在上述示例中,检索器返回的被授权属性为[$.education. schools[*]. name, $.education. schools[*]. major, $.education. schools[*]. stime],指定客户端123对请求URI GET /api/lookup/abc的响应中的name、major和stime字段有访问权限。
响应构建阶段,处理器接收被授权的属性列表和服务的原始响应,执行流式解析并进行属性授权,然后返回转换后的响应。在流式解析过程中,处理器使用预编译的路径匹配器动态地检查每个JSON元素(键、值、对象或数组),确定其是否匹配任何配置规则中的JSONPath表达式。对于匹配的元素,处理器进行提取并保留这些数据。对于不匹配的元素,则将这些数据从最终的响应中过滤掉。这个过程可能涉及临时存储匹配路径下的数据,直到可以确定整个对象或数组是否需要被保留或过滤。一旦完成了对整个响应的流式解析和按需数据提取,处理器便构建出了最终的JSON响应对象,这个对象只包含根据属性授权配置保留的数据。详细算法如下:
基于流式解析构造目标响应算法:
输入:JSON数据流jsonStream, 路径匹配器集合pathMatchers
输出:解析后的JSON对象filteredJson
1.function StreamParseJSON(jsonStream,pathMatchers)
2." 初始化:filteredJson = 空JSON对象
3." "初始化:currentPath = \"\"
4." "对于jsonStream中的每一个事件event进行遍历:
5." " "如果 event是开始对象或数组:
6." " " 更新currentPath(加入新的对象或数组标识)
7." " "否则如果 event是结束对象或数组:
8." " " "更新currentPath(移除最后的对象或数组标识)
9." " "否则如果 event是键值对:
10." " " 完整路径 = currentPath + event的键
11." " " 如果 完整路径 在 pathMatchers中:
12." " " " 将event的键值对添加到filteredJson 中
13." " " 返回filteredJson
4" 复杂度分析
4.1" 时间复杂度
预编译阶段,设有N个JSONPath表达式,每个表达式的平均长度为L,则解析表达式并构建AST的时间复杂度:
T1 ∝ N×L≈hN×L = O(NL)
构建每个路径匹配器的复杂度主要取决于表达式长度,因此时间复杂度为O(L)。于是,总的预编译时间复杂度:
T2 = T1 + O(L) = O(NL)
流式解析与构造阶段,设JSON数据总共有M个元素(包括对象的键值对、数组的元素等),对于一次具体的请求,其对应的路径匹配器只有一个,因此每个JSON元素每次匹配的平均时间复杂度为O(L),则所有元素的匹配时间复杂度:
T3 ∝ M×L≈M×hL = O(ML)
由于JSONPath的预编译是在系统启动阶段执行的一次性动作,所以整个算法的总体时间复杂度主要由运行时流式解析与路径匹配步骤决定,即O(ML)。
4.2" 空间复杂度
由于是流式处理,同时在内存中维护的数据结构大小不依赖于输入数据的总大小,而是取决于预设的JSON数据的最大嵌套深度和最大宽度两个常量,因此空间复杂度为O(1)。
5" 实验研究
实验在以下配置的测试环境中进行:Intel Core i7-9700 CPU @ 3.00 GHz、32GB RAM和512 GB SSD。使用的操作系统为Ubuntu 20.04 LTS,所有测试均在相似的系统负载条件下运行,以确保结果的一致性。响应解析处理器使用Java 11实现,并实现了Archana等[8]工作中提出的基于JSONTree的全量加载解析策略和本文提出的流式解析策略。
实验使用了不同大小和复杂度的JSON数据集来模拟现实世界场景。数据集大小从小(10 KB,代表简单的JSON对象)到大(101 MB,代表深层嵌套和复杂的JSON结构)。每个数据集都使用预定义的属性授权规则进行处理,以根据调用方的clientId过滤敏感信息。实验从响应解析构造时间、内存占用、和CPU使用率3个方面对比了两种策略的性能。
响应解析构造时间实验数据如表3所示。在所有数据集上,流式解析策略一致地显示出处理时间的显著减少,特别是在处理大型响应数据时更为明显。对于最大的数据集(101 MB),流式解析比基于JSONTree的解析方式减少了大约40%的处理时间。
在内存占用方面,实验使用JMeter压力测试工具,逐渐增加并发数量请求响应结构体约为10 MB的接口,同时使用VisualVM观测网关的内存占用情况。实验截图如图3所示,两种策略在不同并发量下的表现如图4所示。可以看出,流式解析场景中的内存占用明显较低,且随着并发量的增长,内存占用量增加缓慢。对于在并发量为150次/秒的场景下,流式解析比基于JSONTree的解析方法使用的内存减少了57%,证明了其高并发场景下执行属性授权的效率。
在CPU使用率方面,实验使用JMeter以固定的并发数量请求响应体积分别为10 KB、1.1 MB、10 MB的3类接口,两种策略在不同响应体积下的表现如图5所示。可以看出,流式解析略微增加了CPU使用率,但考虑到其在内存使用和处理时间上的优势,这一增加是可接受的。
6" 结" 论
本研究提出了一种基于流式解析实现的API网关属性授权策略,相较于已有的解析方法,不仅大幅度降低了内存消耗,还优化了处理时间,虽然以略微增加的CPU使用为代价,但鉴于其带来的综合性能提升,这一代价是值得的。因此,对于API网关这种处理大规模JSON数据,且对内存使用有严格要求的高并发应用场景,流式解析提供了一种更加高效和可行的解决方案。未来的工作可以进一步探索流式解析在不同数据处理场景下的应用,以及如何增强其容错能力,以满足更广泛的应用需求。
参考文献:
[1] 辛园园,钮俊,谢志军,等.微服务体系结构实现框架综述 [J].计算机工程与应用,2018,54(19):10-17.
[2] LIANG Z J,DAI H Q,KANG Y,et al. Research on Authorization Verification Method of API Gateway in Grid Microservice Architecture [C]//International Conference on Electronic Information Engineering and Computer Science (EIECS 2022).Changchun:SPIE,2023:12602H. https://doi.org/10.1117/12.2668095.
[3] ZUO X Y,SU Y H,WANG Q Q,et al. An API Gateway Design Strategy Optimized for Persistence and Coupling [J/OL].Advances in Engineering Software,2020,148[2024-01-15].https://doi.org/10.1016/j.advengsoft.2020.102878.
[4] OLIMPION S,ALEKSANDER B,TAFA I,et al. OAuth2.0 in Securing APIs [EB/OL].2020:44-50[2024-01-20].https://knowledgecenter.ubt-uni.net/conference/2020/all_events/325.
[5] JONES M,BRADLEY J,SAKIMURA N. RFC 7519: JSON Web Token (JWT) [EB/OL].[2024-01-15].https://www.rfc-editor.org/info/rfc7519.
[6] 中华人民共和国中央人民政府.中华人民共和国个人信息保护法 [R/OL].(2021-08-20).https://www.gov.cn/xinwen/2021-08/20/content_5632486.htm.
[7] 中华人民共和国中央人民政府.中华人民共和国数据安全法 [R/OL].(2021-06-11).https://www.gov.cn/xinwen/2021-06/11/content_5616919.htm.
[8] ARCHANA S,MUNNANGI S K. Attribute Authorization - A Novel Enhancement to API Gateways [J].Service-Oriented Computing,2023,14420:276-290.
[9] FRIESEN J. Java XML and JSON: Document Processing for Java SE:2nd Edition [M].[S.I.]:Apress,2019:299-322.
[10] 李莹.美团点评API网关系统网关核心模块的设计与实现 [D].南京:南京大学,2020.
[11] OKTARIA D,GINTING J A M K,ABDUROHMAN M,et al. Design of API Gateway as Middleware on Platform as a Service [J].Indonesia Journal on Computing,2021,6(3):47-62.
[12] NEAMTIU I,FOSTER J S,HICKS M. Understanding Source Code Evolution Using Abstract Syntax Tree Matching [J].Software Engineering Note,2005,30(4):1-5.
作者简介:张礼庆(1994—),男,汉族,江苏徐州人,助理工程师,硕士研究生,研究方向:微服务、高性能架构、数据挖掘。
收稿日期:2024-02-28