# DataMask **Repository Path**: gangzi20008/data-mask ## Basic Information - **Project Name**: DataMask - **Description**: 专注于数据遮罩技术的开源项目,提供高效、安全的数据脱敏解决方案,适用于隐私保护和安全测试场景。 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2025-08-01 - **Last Updated**: 2025-08-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 敏感信息无感脱敏 ```text 1、注解侵入式:属于局部即精确脱敏,常用于相同字段需要不同脱敏规则的场景,其中注解如下: - @Empty: 置空(将敏感字段值取空,非等长) - @Hash: 哈希(将敏感字段值取Hash,非等长) - @Regex: 正则(将敏感字段值通过正则表达式进行替换,非等长) - @Repl: 替换(将敏感字段值根据所指定位置进行替换,等长) - @Mask: 掩盖(将敏感字段值进行*替换,等长,且可采用内置脱敏规则或自定义位置) 2、配置非侵入式:属于全局,常用于与注解侵入式相反的场景,可同时用且局部优先于全局,若局部匹配不到,则不会采用全局匹配,因此最好配置全局规则,且全局规则配置,字段名不区分大小写 3、对于日志脱敏,只支持Logback、Log4j/Log4j2;且需满足如下日志输出格式:(遵循SpEL表达式规范) 1、日志脱敏格式1(只含一个参数,多个占位符或占位符spel表达式):log.info("无表达式={}、不规范spel模板表达式={name}、符合规范spel表达式1={#p0.phone}、符合规范spel表达式2={args[0].bankCard}", user); 2、日志脱敏表达式2(多个参数,多个占位符或占位符spel表达式):log.info("用户名={name}、电话号码={#p0.phone},{}", user, "张三丰", "{\"phone\":\"1772285144\"}"); 3、日志脱敏格式3(只含占位符即不含占位符spel表达式,参数个数多余有效占位符):log.info("转义占位符(此时占位符属于无效)=\\{}、用户名={}、电话号码={}", user.getAddr(), user.getName(), user.getPhone()); 4、日志脱敏格式4(只含占位符即不含占位符spel表达式,参数个数小于有效占位符):log.info("{}、用户名={name}、电话号码={Phone}、{}", user.getAddr(), user.getName(), user.getPhone()); 注意: 1)若无法解析该占位符的spel表达式时,当参数仅且只有一个,若非空表达式则无论多少个有效(非被转义)占位符,都始终指向该参数取值 2)否则取表达式的有效占位符所在日志模板位置中索引对应的参数(即同日志框架一样按有效占位符的索引获取参数) 3)而当表达式为空时,同日志框架一样按有效占位符的索引获取参数,否则先根据从上1)和2)中所获取到的参数中进行按表达式取值 4)若取不到即null,则判断是否是简单值类型或简单值类型的数组 5)若是则按照表达式和该参数进行脱敏,否则null 6)若占位符对应的值为JSON或XML字符串时,同样会对其进行脱敏 7)与日志框架不同1:占位符不能只出现左{,但可以只出现右},否则需要使用\进行转义占位符,如:\{}或\{ 8)与日志框架不同2:占位符中间存在空格,会进行去空格处理且视为有效占位符,而日志框架不会,同时也不会视为有效占位符 9)与日志框架不同3:占位符中间存在表达式,会按照spel表达式方式解析,而对于无法解析的表达式,则会先根据表达式对应的占位符的索引去获取对应的参数, 然后从该参数中获取该表达式的值,按照4)和5)进行处理,而日志框架不会。如:{name},当spel根据参数消息无法解析name属性的值时,则会先根据name对应的占位符的索引去获取对应的参数, 然后从该参数中获取该表达式的值,按照4)和5)进行处理 日志框架有以下组合: 1)slf4j + logback: slf4j-api.jar + logback-classic.jar + logback-core.jar 2)slf4j + log4j: slf4j-api.jar + slf4j-log412.jar + log4j.jar 3)slf4j + jul: slf4j-api.jar + slf4j-jdk14.jar 4)也可以只用slf4j无日志实现:slf4j-api.jar + slf4j-nop.jar 注log4j2配合需要导入log4j2的log4j-api.jar、log4j-core.jar和桥接包log4j-slf4j-impl.jar。 所谓的桥接包,就是实现StaticLoggerBinder类,用来连接slf4j和日志框架。因为log4j和log4j2刚开始没有StaticLoggerBinder这个类, 为了不改变程序结构,只能重新写一个新的jar来实现StaticLoggerBinder。而logback出现slf4j之后,于是在logback本身的jar中实现了StaticLoggerBinder,所以就不需要桥接包 4、对于网页脱敏,当采用@ResponseBody修饰或返回类型为ResponseEntity的Restful接口时(即JSON或XML),默认会脱敏,若不需要脱敏则使用@Desensitization(enabled=false)禁用脱敏,例如与第三方进行接口交互 5、若需要根据用户权限脱敏页面即WEB场景,则可以实现UserMaskPermission接口,并加入Spring容器管理 6、针对于@Mask内置脱敏规则有: 1)姓名(FULL_NAME):默认自动根据字符长度显示,当长度小于等于2,则显示第1个字符,否则显示前2个字符 2)手机号(MOBILE_PHONE):大陆-11位、台湾-10位、香港澳门-8位。默认自动根据字符长度显示大陆-前3后4、台湾-前3后3、香港澳门-前2后2 3)固话(FIXED_PHONE):由3~4位区号+7~8位固定数字组成。默认自动根据字符长度显示,当区号小于等于3,则显示前3后2,否则前4后2 4)身份证号(ID_CARD):由6位地址码+8位出生日期+3位顺序码+1位校验码,有15位或18位。默认显示前3后4 5)地址(ADDRESS):默认自动根据字符长度显示,当长度大于6,则显示前6,则显示前7 6)电子邮件(EMAIL):默认自动根据@前字符长度显示,且@后字符显示,当@前字符长度小于3,则@前字符全显示,否则显示前三位及@后 7)中国大陆车牌(CAR_LICENSE):由1个汉字+1个字母+5~6字母和数字组成。默认显示前2后2 8)银行卡(BANK_CARD):默认显示前6后4 9)护照(PASSPORT):由1位字母(护照类型)+8位数字组成。默认显示前1后3 10)数值(NUMBER):默认显示第1位 对于日期,则采用正则处理,如默认显示年份:(.+年)?(.+月)?(.+日)?.+ ;而若自定义显示,格式:前,后,如前3后4显示(3,4)、前3显示(3)、后4显示(,4),如:@Mask(show = @CustomShow(pre = 3, suf = 4)) 7、脱敏策略: 1)packages:脱敏范围即配置包路径,多个值时以英文逗号隔开;为了减少不必要的数据脱敏,否则会影响系统性能,因此推荐设置。默认:空,当为空时,会扫描全部类 2)effectDate:脱敏生效期 3)expiryDate:脱敏失效期 8、只支持脱敏key所对应字符类型,而key所对应枚举、基本类型等类型不支持,若需要脱敏数值类型,则key必须采用字符类型修饰,如:String amount = "3000.01"; 注:若是JSON或XML字符串,则同样会进行脱敏 ``` ## 注解侵入式案列 ```text 1、电话号码177*****144:@Mask(type = SensitiveTypeEnum.MOBILE_PHONE) 2、电子邮箱133***@qq.com:@Regex(pattern = "(\\w{3})\\w+(@qq.com)", rv = "$1***$2") 3、身份证:@Hash(algorithm = Hash.AlgorithmEnum.MD5, salt = "ws@4q#") 4、地址:@Repl(posns = {@Repl.Posn(i = 3), @Repl.Posn(i = 8, rv = "#?12$%34")}) ``` ## 配置非侵入式案列 ```yaml ouo: desensitization: #启动脱敏 enabled: true #脱敏范围即配置包路径,多个值时以英文逗号隔开;为了减少不必要的数据脱敏,否则会影响系统性能,因此推荐设置。默认:空,当为空时,会扫描全部类 #scan: xx.xx,yy.yy #脱敏规则列表 rules: #字段名 - field: name #脱敏模式:置空empty、哈希hash、正则regex、替换replace、掩盖mask mode: mask #脱敏场景:日志log、网页web、全部all,默认all scene: log #敏感类型,采用内置脱敏配置 type: full_name - field: phone mode: replace scene: all posns: - i: 3 - i: 8 #是否固定值,默认true,false为随机值 fixed: true #替换值 rv: "#" #剩余位置 surplus: fixed: false - field: id_card mode: hash scene: web #算法 algorithm: sm3 #盐 salt: grvyw$2 - field: addr mode: empty - field: ip mode: regex #正则表达式 pattern: (\\d{3})\\d{4}(\\d{4}) rv: $1####$2 ```