数据脱敏
TIP
对 Vo 等 JSON 输出 字段使用 @SensitivityEncrypt,由 SensitivitySerializer 在 Jackson 序列化时按类型做掩码;仅影响序列化结果,不等同于数据库加密存储。
注解
- 定义:
com.sxpcwlkj.common.annotation.SensitivityEncrypt - 配合:
@JsonSerialize(通过@JacksonAnnotationsInside已内置)
java
import com.sxpcwlkj.common.annotation.SensitivityEncrypt;
import com.sxpcwlkj.common.enums.SensitivityTypeEnum;
// 手机号
@SensitivityEncrypt(type = SensitivityTypeEnum.PHONE)
private String phoneNumber;类型枚举 SensitivityTypeEnum
- 完整类名:
com.sxpcwlkj.common.enums.SensitivityTypeEnum - 模块:
mms-modules/mms-common - 声明方式:
public enum,带 Lombok@Getter(仅为枚举常规 getter;本枚举无附加字段,故与默认name()/ordinal()并存)。
当前源码中仅下列 5 个枚举常量(依 Java 声明顺序,ordinal() 为 0~4)。若本地工程已新增常量,以仓库实际文件为准。
源码全文(与仓库一致)
以下为 SensitivityTypeEnum.java 的镜像(包名、import、类注释、常量注释与主仓一致),便于对照与检索。
java
package com.sxpcwlkj.common.enums;
import lombok.Getter;
/**
* 脱敏
* @author: mmsAdmin
* @date: 2020/11/17 14:44
* @description:
*/
@Getter
public enum SensitivityTypeEnum {
/**
* 姓名
*/
NAME,
/**
* 身份证号
*/
ID_CARD,
/**
* 邮箱
*/
EMAIL,
/**
* 手机号
*/
PHONE,
/**
* 自定义(此项需设置脱敏的前置后置长度)
*/
CUSTOMER,
}常量一览(写全)
ordinal() | 枚举常量 | 字段注释(源码) | SensitivitySerializer 分支 | SensitivityUtil 方法 | 规则摘要(与实现一致) |
|---|---|---|---|---|---|
| 0 | NAME | 姓名 | case NAME | hideChineseName | 内部调用 desValue(origin, 1, 0, "*"):仅首字符明文,其后每位为 * |
| 1 | ID_CARD | 身份证号 | case ID_CARD | hideIDCard | 正则替换:(\\d{4})\\d{10}(\\w{4}) → $1*****$2,即 前 4 + 中间 5 位 * + 后 4(按 18 位大陆身份证 形态设计,其它证件勿直接套用) |
| 2 | EMAIL | 邮箱 | case EMAIL | hideEmail | 正则:(\\w?)(\\w+)(\\w)(@\\w+\\.[a-z]+(\\.[a-z]+)?) → $1****$3$4,即 首字符 + **** + @ 前末字符 + 域名 |
| 3 | PHONE | 手机号 | case PHONE | hidePhone | 正则:(\\d{3})\\d{4}(\\d{4}) → $1****$2,即 前 3 + **** + 后 4(11 位手机号形态) |
| 4 | CUSTOMER | 自定义(此项需设置脱敏的前置后置长度) | case CUSTOMER | desValue | 使用 @SensitivityEncrypt 的 prefixNoMaskLen、suffixNoMaskLen、symbol 调用 desValue;中间段逐字符替换为 symbol |
未覆盖值:SensitivitySerializer 的 switch 对以上 5 类穷举;若传入扩展枚举却未改切面,会落入 default → IllegalArgumentException(源码:unknown privacy type enum)。
与 @SensitivityEncrypt 的关系
- 非
CUSTOMER:仅type生效,固定走对应SensitivityUtil方法。 CUSTOMER:除type外必须使用prefixNoMaskLen/suffixNoMaskLen/symbol(注解带默认值,与文档「自定义掩码」章节一致)。
相关类:SensitivityTypeEnum、SensitivitySerializer、SensitivityUtil、SensitivityEncrypt。
按场景的用法说明
下列为常见脱敏需求与推荐做法。除内置枚举已覆盖的类型外,多数可用 CUSTOMER 按「前后保留字符数」近似实现;规则复杂(正则、分段、多分隔符)时,建议在 SensitivityUtil 增加专用方法并在 SensitivitySerializer 中扩展 switch 分支,避免注释写很长却仍难调参。
银行卡号
- 展示习惯:常保留 前 4 位 + 后 4 位,中间打星;卡号长度多为 16~19 位(以实际卡 BIN 与发卡行为准)。
- 注解示例:
type = CUSTOMER,prefixNoMaskLen = 4,suffixNoMaskLen = 4,symbol = "*"。 - 注意:需符合支付合规时,接口侧可能直接 不返回 完整卡号,仅返回掩码或 token,不止 JSON 脱敏一层。
地址(省 / 市 / 区 + 门牌)
- 推荐:库表或 Vo 拆分「省市区」与「详细地址」字段;省市区可原样或轻度脱敏,详细门牌、楼栋室号单独字段做
CUSTOMER或高强度掩码。 - 若仅为一条长字符串:只能按字符估算,
prefixNoMaskLen取省市区大致字数,剩余中间一律掩码;准确性不如结构化字段。
IP / MAC
- IPv4:例如保留 前两段(如
192.168.x.x),可按字符串数到第二段结束位置设prefixNoMaskLen(需按实际x.x.x.x长度数点,没有统一魔法数字);或扩展工具方法按.分段处理更稳妥。 - MAC:习惯保留 首段或首尾若干字符(如
AA:**:**:**:**:BB),可用CUSTOMER设前后保留长度,或专用工具按:分段。 - 说明:IP/MAC 多用于审计、风控;对外接口是否返回全量请以安全策略为准。
护照、港澳通行证等证件号
- 与身份证区别:内置
ID_CARD对应hideIDCard的 18 位大陆身份证规则,不宜直接套在护照号、港澳通行证号上(长度、字母数字组合各异)。 - 做法:优先
CUSTOMER(前后各保留少量字符);若项目内证件类型固定,可 新增枚举 +SensitivityUtil方法 +SensitivitySerializer分支,与身份证并列维护。
车牌号
- 展示习惯:常保留 地区发牌代号(汉字 + 字母)及 末位 等,中间掩码;新能源与普通车牌长度不同。
- 做法:按字符串长度调
CUSTOMER的前后保留位;规则稳定时建议 专用工具方法,避免魔法数字散落在各 Vo。
微信 / 支付宝等账号展示名
- 习惯:首尾少量字可见,中间
*(与昵称长度相关)。 - 做法:短昵称可用
CUSTOMER(如首尾各 1);较长可用prefixNoMaskLen = 1、suffixNoMaskLen = 1与symbol = "*",效果接近「中间打星」。
密码类字段(与「序列化脱敏」不同)
- 登录密码、支付密码、口令、Token 原文等:接口响应与日志中通常不应出现明文。
- 常见手段:
- Vo / DTO 不包含该字段,或对出参 DTO 使用
@JsonIgnore等 不序列化; - 日志中使用
SensitiveOps或统一占位******,而不是依赖@SensitivityEncrypt做「美化展示」; - 存储侧使用哈希 / 加密由安全方案单独设计。
- Vo / DTO 不包含该字段,或对出参 DTO 使用
- 小结:
@SensitivityEncrypt面向「仍需露出部分信息的可读字段」;密码类属于 禁止输出或固定占位,归 接口设计、日志、存储 另一类处理。
自定义掩码(CUSTOMER)
CUSTOMER 走 SensitivityUtil.desValue:对字符串从左到右,前 prefixNoMaskLen、后 suffixNoMaskLen 个字符保留,中间每个字符替换为 symbol(默认一个 * 占一位)。
| 属性 | 说明 | 默认 |
|---|---|---|
prefixNoMaskLen | 前缀不脱敏长度 | 1 |
suffixNoMaskLen | 后缀不脱敏长度 | 1 |
symbol | 掩码字符 | * |
java
@SensitivityEncrypt(
type = SensitivityTypeEnum.CUSTOMER,
prefixNoMaskLen = 4,
suffixNoMaskLen = 4,
symbol = "*"
)
private String bankCardNo;Excel 与日志
- Excel 导出等场景若需脱敏,可能使用
SensitivitySerializer之外的SensitiveOps工具方法或导出模板配置,以具体导出代码为准。 - 空值:当前
SensitivitySerializer在 原始值为 null、空串或未识别类型 等分支下会写出 空字符串""(以源码为准);若需null不回传,请在 Vo 层或全局序列化策略另行约定。
