sensitive脱敏框架

依赖

脱敏包

<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>

配置

logback.xml

<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>

项目里面的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>

前台数据展示隐藏

脱敏注解

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;
}

拦截器

运行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类型的返回结果进行拦截,通过 SensitiveUtil.desCopy(UserInfo)进行脱敏

@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,进行脱敏处理
        switch (((Result<?>) body).getData()) {
        case UserInfo userInfo:
            ((Result<UserInfo>) body).setData(SensitiveUtil.desCopy(userInfo));

        default:
             return body;
            }

        return body;
    }

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部