【数据脱敏方案】不使用 AOP + 注解,使用 SpringBoot+YAML 实现
文章目录
- 引入
- 认识 YAML 格式规范
- 定义脱敏规则格式
- 脱敏逻辑实现
- 读取 YAML 配置文件获取脱敏规则
- 通过键路径获取对应字段规则
- 原始
- 优化后
- 对数据进行脱敏处理
- 递归生成字段对应的键路径
- 脱敏测试
- 完整工具类
引入
在项目中遇到一个需求,需要对交易接口返回结果中的指定字段进行脱敏操作,但又不能使用AOP+注解的形式,于是决定使用一种比较笨的方法:
- 首先将所有需要脱敏字段及其对应脱敏规则存储到 Map 中。
- 在接口返回时,遍历结果中的所有字段,判断字段名在 Map 中是否存在:
- 如果不存在:说明该字段不需要脱敏,不做处理即可。
- 如果存在:说明该字段需要脱敏,从 Map 中获取对应的脱敏规则进行脱敏。
- 最后返回脱敏之后的结果。
认识 YAML 格式规范
由于返回的结果涉及到嵌套 Map,所以决定采用 YAML 格式的文件存储脱敏规则,那么为了大家统一维护和开发,就需要大家对 YAML 格式进行了解,遵守规范,不易出错,少走弯路。
YAML(YAML Ain’t Markup Language)与传统的 JSON、XML 和 Properties 文件一样,都是用于数据序列化的格式,常用于配置文件和数据传输。
相比于其他格式,YAML 是一种轻量级的数据序列化格式,它的设计初衷是为了简化复杂性,提高人类可读性,并且易于实现和解析。
-
与 JSON 相比:YAML 在语法上更为灵活,允许使用更简洁的方式来表示数据结构。
-
与 XML 相比:YAML 的语法更为简洁,没有繁琐的标签和尖括号。
-
与 Properties 相比:YAML 支持更复杂的数据结构,包括嵌套的键值对和列表。
除此之外,YAML 还支持跨平台、跨语言,可以被多种编程语言解析,这使得YAML非常适合用于不同语言之间的数据传输和交换。
YAML 文件的语法非常简洁明了,以下是它的语法规范:
-
基本语法:
- 使用 缩进表示层级关系,可以使用空格或制表符进行缩进,但不能混用。
- 使用冒号(:)表示键值对,键值对之间使用换行分隔。
- 使用破折号(-)表示列表项,列表项之间也使用换行分隔。
# 使用缩进表示层级关系 server: port: 8080 # 使用冒号表示键值对 name: John Smith age: 30 # 使用破折号表示列表项 hobbies: - reading - hiking - swimming
-
注释:
- 使用井号(#)表示注释,在 # 后面的内容被视为注释,可以出现在行首或行尾。
# 这是一个注释 name: John Smith age: 30 # 这也是一个注释
-
字符串:
- 字符串可以使用单引号或双引号括起来,也可以不使用引号。
- 使用双引号时,可以使用转义字符(如 \n 表示换行)和转义序列(如 \u 表示 Unicode 字符)。
# 使用双引号表示字符串 name: "John Smith" # 使用单引号表示字符串 nickname: 'Johnny'
-
键值对:
- 键值对使用冒号(:)表示,键和值之间使用一个 空格 分隔。
- 键可以是字符串或纯量(如整数、布尔值等)。
- 值可以是字符串、纯量、列表或嵌套的键值对。
# 键和值之间使用一个空格分隔 name: John Smith # 键可以是字符串或纯量 age: 30 # 值可以是字符串、纯量、列表或嵌套的键值对 address: city: San Francisco state: California zip: 94107
-
列表:
- 使用破折号(-)表示列表项。
- 列表项可以是字符串、纯量或嵌套的列表或键值对。
# 使用破折号表示列表项 hobbies: - reading - hiking - swimming # 列表项可以是字符串、纯量或嵌套的列表或键值对 people: - name: John Smith age: 30 - name: Jane Doe age: 25
-
引用:
(图片来源网络,侵删)- 使用&表示引用,使用*表示引用的内容。
# 使用&表示引用 address: &myaddress city: San Francisco state: California zip: 94107 # 使用*表示引用的内容 shippingAddress: *myaddress
-
多行文本块:
- 使用|保留换行符,保留文本块的精确格式。
- 使用>折叠换行符,将文本块折叠成一行,并根据内容自动换行。
# 使用|保留换行符 description: | This is a multi-line string. # 使用>折叠换行符 summary: > This is a summary that may contain line breaks.
-
数据类型:
(图片来源网络,侵删)- YAML支持多种数据类型,包括字符串、整数、浮点数、布尔值、日期和时间等。
- 可以使用标记来表示一些特殊的数据类型,如 !!str 表示字符串类型、!!int 表示整数类型等。
# 使用标记表示数据类型 age: !!int 30 weight: !!float 65.5 isMale: !!bool true created: !!timestamp '2022-01-01 12:00:00'
-
多文件:
- 可以使用—表示多个 YAML 文件之间的分隔符。每个文件可以使用任何 YAML 语法。
# 第一个YAML文件 name: John Smith age: 30 --- # 第二个YAML文件 hobbies: - reading - hiking - swimming
- 可以使用—表示多个 YAML 文件之间的分隔符。每个文件可以使用任何 YAML 语法。
- 使用&表示引用,使用*表示引用的内容。
- 使用井号(#)表示注释,在 # 后面的内容被视为注释,可以出现在行首或行尾。
定义脱敏规则格式
对于数据结构简单的接口返回结果,脱敏规则格式定义为【交易号->字段->规则】:
(图片来源网络,侵删)交易号: 字段名: 规则: '/^(1[3-9][0-9])\d{4}(\d{4}$)/'
同时接口返回的结果中可能用有嵌套列表,那么针对这种复杂的结构就定义格式为【交易号->字段(列表)->字段->规则】,即:
交易号: 字段名(列表): 字段名: 规则: '/^(1[3-9][0-9])\d{4}(\d{4}$)/'
使用这种层级结构,我们完全可以通过 Map.get("Key") 的形式获取到指定交易,指定字段的脱敏规则。
脱敏逻辑实现
读取 YAML 配置文件获取脱敏规则
-
首先创建 YAML 文件 desensitize.yml 添加对应交易字段的脱敏规则:
Y3800: phone: rule: "(\\d{3})\\d{4}(\\d{4})" format: "$1****$2" idCard: rule: "(?
-