Skip to content

数据脱敏 ​

这篇解决什么 ​

接口 JSON 里常带着手机号、邮箱、身份证。读完能在 RespVO 上挂 @MobileDesensitize / @IdCardDesensitize,改滑块或正则规则,以及按角色、权限跳过脱敏。

默认端口 48080,管理端前缀 /admin-api。脱敏只改写出的字符串,不改库。

示意图:Controller 仍拿明文 VO;Jackson 写 JSON 时才替换。

只挡响应,不改库

注解走 @JsonSerialize,只在序列化时生效。AdminUserDO、数据库、日志里的原值不会被改。ExcelUtils.write 直接读字段,也不走这条链路,导出仍是明文。

组件位置 ​

名称说明仓库路径
@DesensitizeBy元注解。指定处理器,并挂上 Jackson 序列化器ruoyi-office/yudao-framework/yudao-spring-boot-starter-web/.../desensitize/core/base/annotation/DesensitizeBy.java
StringDesensitizeSerializer读字段上的脱敏注解,调用 handler同模块 .../base/serializer/StringDesensitizeSerializer.java
DesensitizationHandlerdesensitize(origin, annotation);disable 为 true 则原样返回.../base/handler/DesensitizationHandler.java
内置注解滑块、正则两套,字段上直接用.../desensitize/core/slider/annotation/、.../regex/annotation/
单测样例JsonUtils.toJsonString 后再反序列化,核对替换结果.../src/test/java/.../desensitize/core/DesensitizeTest.java

@DesensitizeBy 本身带 @JacksonAnnotationsInside 和 @JsonSerialize(using = StringDesensitizeSerializer.class)。业务注解再套一层即可。

挂到用户 VO ​

UserController 的 /get、/page 返回 UserRespVO。类里已有 mobile、email,加上注解后,管理端列表和详情的 JSON 就会挡住明文:

java
@Schema(description = "用户邮箱", example = "admin@ruoyioffice.com")
@ExcelProperty("用户邮箱")
@EmailDesensitize
private String email;

@Schema(description = "手机号码", example = "15601691300")
@ExcelProperty("手机号码")
@MobileDesensitize
private String mobile;
名称说明仓库路径
UserRespVO用户出参,含手机、邮箱ruoyi-office/yudao-module-system/.../controller/admin/user/vo/user/UserRespVO.java
UserController@RequestMapping("/system/user")ruoyi-office/yudao-module-system/.../controller/admin/user/UserController.java
EmployeeRespVO员工出参,含身份证、手机ruoyi-office/yudao-module-hrm/.../controller/admin/employee/vo/EmployeeRespVO.java

身份证不在用户 VO 上。人力资源 EmployeeRespVO.idCard 挂 @IdCardDesensitize 即可。

先用内置注解

手机、邮箱、身份证、银行卡、车牌、中文名、密码都有现成注解。默认前后缀够用时,不必再写 handler。

滑块脱敏 ​

@SliderDesensitize 按 prefixKeep、suffixKeep 留明文,中间用 replacer 填满。字符串不够长时,整段替换。

13248765917 配前 3 后 4、replacer=*,写出 132****5917。

名称说明仓库路径
@SliderDesensitize通用滑块。可改前后缀和替换符.../slider/annotation/SliderDesensitize.java
@MobileDesensitize默认前 3 后 4。13248765917 → 132****5917MobileDesensitize.java
@IdCardDesensitize默认前 6 后 2。530321199204074611 → 530321**********11IdCardDesensitize.java
@FixedPhoneDesensitize默认前 4 后 2。01086551122 → 0108*****22FixedPhoneDesensitize.java
@BankCardDesensitize默认前 6 后 2。9988002866797031 → 998800********31BankCardDesensitize.java
@PasswordDesensitize前后缀默认 0,整段替换。123456 → ******PasswordDesensitize.java
@CarLicenseDesensitize默认前 3 后 1。粤A66666 → 粤A6***6CarLicenseDesensitize.java
@ChineseNameDesensitize默认前 1 后 0。刘子豪 → 刘**ChineseNameDesensitize.java
AbstractSliderDesensitizationHandler读注解属性,拼中间替换段.../slider/handler/AbstractSliderDesensitizationHandler.java

前后缀不够用时,直接改注解参数:

java
@SliderDesensitize(prefixKeep = 3, suffixKeep = 3)
private String slider2; // ABCDEFG → ABC*EFG

prefixKeep = 10 且原文更短时,整段变成 *******。替换符也可以改成 #。

正则脱敏 ​

@RegexDesensitize 对原文做 replaceAll(regex, replacer)。默认 regex 匹配整段,replacer 为 ******。

regex=123、replacer=****** 时,123456789 写成 ******456789。

名称说明仓库路径
@RegexDesensitize通用正则。可改 regex、replacer.../regex/annotation/RegexDesensitize.java
@EmailDesensitize默认 (^.)[^@]*(@.*$),替换 $1****$2。example@gmail.com → e****@gmail.comEmailDesensitize.java
AbstractRegexDesensitizationHandler先算 disable,再 replaceAll.../regex/handler/AbstractRegexDesensitizationHandler.java

邮箱已经有专用注解,一般不用自己写正则。

按角色或权限跳过 ​

每条内置注解都有 disable,值是 Spring EL。表达式为 true 时返回原文。ss Bean 就是权限篇里的 SecurityFrameworkService。

超管看完整手机号:

java
@MobileDesensitize(disable = "@ss.hasRole('super_admin')")
private String mobile;

按权限标识放开:

java
@MobileDesensitize(disable = "@ss.hasPermission('system:user:query')")
private String mobile;
名称说明仓库路径
disable空串不解析,继续脱敏各 *Desensitize 注解
@ss.hasRole角色 code,超管是 super_adminRoleCodeEnum.SUPER_ADMIN
@ss.hasPermission菜单权限标识例如 system:user:query
SpringExpressionUtils用 Bean 工厂解析 ELruoyi-office/yudao-framework/yudao-common/.../SpringExpressionUtils.java

disable 为 true 表示「这次不脱敏」。要挡住某人,不要把表达式写反。

自定义注解 ​

内置规则盖不住时,自己写一个字段注解,再用 @DesensitizeBy 指定处理器。

java
@Documented
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@DesensitizeBy(handler = AddressHandler.class)
public @interface Address {

    String replacer() default "*";
}

处理器实现 DesensitizationHandler<Address>,或继承滑块 / 正则抽象类,复用 disable 和拼接逻辑。测试包里的 Address / AddressHandler 是完整样例。

名称说明仓库路径
@DesensitizeBy声明 handler,并接入 Jackson见上文
Address自定义注解示例.../src/test/java/.../desensitize/core/annotation/Address.java
AddressHandler对应处理器.../src/test/java/.../desensitize/core/handler/AddressHandler.java

业务注解放到对应模块即可,不必塞进 Web Starter。

代码里直接脱敏 ​

接口出参走注解。日志、第三方报文要当场挡一段字符串,用 Hutool DesensitizedUtil。社交模块上传小程序发货信息时,收件人手机号就是这样处理的:

java
DesensitizedUtil.mobilePhone(reqDTO.getReceiverContact())
名称说明仓库路径
DesensitizedUtil手机、身份证、邮箱、银行卡等工具方法Hutool
发货收件人调用前先挡手机号ruoyi-office/yudao-module-system/.../service/social/SocialClientServiceImpl.java

这段调用写在 Service 里,和 Jackson 注解无关。不要把它写回 DO 再 update,否则库里会变成掩码。

配置与操作 ​

在 RespVO 字段加 @MobileDesensitize 等,只影响 JSON 输出。不要把掩码写回数据库。

开启见 框架层。

相关篇 ​

联系我们

获取报价、演示和二开方案

微信咨询二维码

微信咨询

17156169080

添加时备注「RuoYi Office」

在线体验商业版