sensitive敏感信息脱敏
有一些敏感信息,比如手机号、身份证号等,需要在日志,以及页面展示的时候进行脱敏。避免数据泄露。
步骤
1.选择脱敏框架
sensitive框架:https://github.com/houbb/sensitive
2.maven引入
引入核心脱敏包
<dependency>
<groupId>com.github.houbb</groupId>
<artifactId>sensitive-logback</artifactId>
<version>1.7.0</version>
</dependency>
引入 logback 依赖包
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
3.logback.xml 配置
下面是logback模版:
<configuration>
<!-- 基于 converter -->
<conversionRule conversionWord="sensitive" converterClass="com.github.houbb.sensitive.logback.converter.SensitiveLogbackConverter" />
<!-- 使用 converter -->
<appender name="STDOUTConverter" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %sensitive%n</pattern>
</encoder>
</appender>
<!-- 使用 layout -->
<appender name="STDOUTLayout" class="ch.qos.logback.core.ConsoleAppender">
<layout class="com.github.houbb.sensitive.logback.layout.SensitiveLogbackLayout">
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</layout>
</appender>
<!-- 设置根日志级别为DEBUG,并将日志输出到控制台 -->
<root level="DEBUG">
<appender-ref ref="STDOUTConverter"/>
<appender-ref ref="STDOUTLayout"/>
</root>
</configuration>
这里共计支持 Converter 和 Layout 两种模式,任选一个即可。
建议使用 SensitiveLogbackConverter,脱敏日志内容。
配置项目里面的logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<springProperty scope="context" name="app.name" source="spring.application.name"/>
<!-- 基于 converter -->
<conversionRule conversionWord="sensitive" converterClass="com.github.houbb.sensitive.logback.converter.SensitiveLogbackConverter" />
<property name="APP_NAME" value="${app.name}"/>
<property name="LOG_PATH" value="${user.home}/${APP_NAME}/logs"/>
<property name="LOG_FILE" value="${LOG_PATH}/application.log"/>
<property name="FILE_LOG_PATTERN" value="%d %-5level [%thread %logger - %sensitive%n"/>
<appender name="APPLICATION"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE}</file>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxHistory>7</maxHistory>
<maxFileSize>50MB</maxFileSize>
<totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
</appender>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf8</charset>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="APPLICATION"/>
</root>
</configuration>
其中需要关注的是converter引入
<conversionRule conversionWord="sensitive" converterClass="com.github.houbb.sensitive.logback.converter.SensitiveLogbackConverter" />
还有日志格式配置
<property name="FILE_LOG_PATTERN" value="%d %-5level [%thread %logger - %sensitive%n"/>
4.日志效果
脱密效果如下:
2025-09-26 09:55:50,260 INFO [http-nio-8085-exec-10 cn.mifu.nft.turbo.rpc.facade.FacadeAspect - start to execute , method = auth , args = [{"idCard":"2****************2|EDB6003794DD4ED72CFA72F54CF4280D","realName":"张三","userId":9}
5.脱敏前台展示字段
脱敏注解举例
public class Example {
@SensitiveStrategyChineseName
private String username;
@SensitiveStrategyPassword
private String password;
@SensitiveStrategyPassport
private String passport;
@SensitiveStrategyIdNo
private String idNo;
@SensitiveStrategyCardId
private String bandCardId;
@SensitiveStrategyPhone
private String phone;
@SensitiveStrategyEmail
private String email;
@SensitiveStrategyAddress
private String address;
@SensitiveStrategyBirthday
private String birthday;
@SensitiveStrategyGps
private String gps;
@SensitiveStrategyIp
private String ip;
@SensitiveStrategyMaskAll
private String maskAll;
@SensitiveStrategyMaskHalf
private String maskHalf;
@SensitiveStrategyMaskRange
private String maskRange;
}
具体操作
@Setter
@Getter
@TableName("users")
public class User extends BaseEntity {
/**
* 手机号
*/
@SensitiveStrategyPhone
private String telephone;
}
增加一个拦截
当运行getUserInfo的时候
@GetMapping("/getUserInfo")
public Result<UserInfo> getUserInfo() {
String userId = (String) StpUtil.getLoginId();
UserQueryRequest request = new UserQueryRequest();
request.setUserId(Long.valueOf(userId));
User user = userService.findById(Long.valueOf(userId));
if (user == null) {
throw new UserException(USER_NOT_EXIST);
}
return Result.success(UserConvertor.INSTANCE.mapToVo(user));
}
对Result类型的返回结果进行拦截
@ControllerAdvice
public class SensitiveResponseBodyAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
// 只对特定类型的返回值执行处理逻辑,这里可以根据需要调整判断条件
return Result.class.isAssignableFrom(returnType.getParameterType());
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
// 如果返回的对象是UserInfo,进行脱敏处理
if (body instanceof Result && ((Result<?>) body).getData() instanceof UserInfo) {
Result<UserInfo> result = (Result<UserInfo>) body;
UserInfo userInfo = result.getData();
User user=UserConvertor.INSTANCE.mapToEntity(userInfo);
user = SensitiveUtil.desCopy(user);
result.setData(UserConvertor.INSTANCE.mapToVo(user));
return result;
}
return body;
}
然后判断返回对象是UserInfo,通过 SensitiveUtil.desCopy(user)进行脱敏
5.个性化配置
用户可以在应用 resources 下通过 chars-scan-config.properties 配置文件指定。
默认配置
SensitivePatternLayout 配置默认为:
chars.scan.prefix=::,,'"‘“=| +()()
chars.scan.scanList=1,2,3,4,9
chars.scan.replaceList=1,2,3,4,9
chars.scan.defaultReplace=12
chars.scan.replaceHash=md5
chars.scan.whiteList=""
属性说明
SensitivePatternLayout 策略的属性说明。
| 属性 | 说明 | 默认值 | 备注 |
| prefix | 需要脱敏信息的匹配前缀 | ::,,'"‘“= +()() 和英文竖线 | 降低误判率 |
| replaceHash | 哈希策略模式 | md5 | 支持 md5/none 两种模式 |
| scanList | 敏感扫描策略列表 | 1,2,3,4 | 1~10 内置的10种敏感信息扫描策略,多个用逗号隔开 |
| replaceList | 敏感替换策略列表 | 1,2,3,4 | 1~10 内置的10种敏感信息替换策略,多个用逗号隔开 |
| defaultReplace | 敏感替换默认策略 | 12 | 1~13 内置的13种敏感信息替换策略,指定一个。当列表没有匹配时,默认使用这个 |
| whiteList | 白名单 | `` | 希望跳过处理的白名单信息 |
其中 1-13 的内置策略说明如下:
| 策略标识 | 说明 |
| 1 | 手机号 |
| 2 | 身份证 |
| 3 | 银行卡 |
| 4 | 邮箱 |
| 5 | 中国人名 |
| 6 | 出生日期 |
| 7 | GPS |
| 8 | IPV4 |
| 9 | 地址 |
| 10 | 护照 |
| 11 | 匹配任意不掩盖 |
| 12 | 匹配任意半掩盖 |
| 13 | 匹配任意全掩盖 |
| m1 | 数字类合并操作(m1:1&2&3) 性能更好 |
| m3 | 拓展类合并操作(m3:4&5&9) 性能更好 |