SpringBoot与Logback整合,实现敏感信息日志脱敏并且异步高效写入​功能

开发 前端
​Logback 是一个强大且灵活的日志框架,适用于各种规模的应用程序。通过自定义 Appender,可以实现复杂的日志处理逻辑,如敏感信息脱敏和异步写入,从而提升系统的安全性和性能。

Logback 是一个强大且灵活的日志框架,适用于各种规模的应用程序。通过自定义 Appender,可以实现复杂的日志处理逻辑,如敏感信息脱敏和异步写入,从而提升系统的安全性和性能。

工作流程

图片图片

为什么需要自定义 Appender?

在某些情况下,默认的 Appender 无法满足特定需求,例如:

  • 自动脱敏敏感信息。
  • 异步处理日志以提高性能。
  • 将日志发送到外部系统或服务。

代码实操

<!-- Disruptor -->
    <dependency>
        <groupId>com.lmax</groupId>
        <artifactId>disruptor</artifactId>
        <version>3.4.4</version>
    </dependency>

    <!-- Logback Classic -->
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
    </dependency>

创建自定义Appender

创建一个名为SensitiveDataMaskingAppender的类,该类继承自AppenderBase<ILoggingEvent>,并在其中使用Disruptor队列进行异步处理。

package com.example.demo.logging;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase;
import com.lmax.disruptor.*;
import com.lmax.disruptor.dsl.Disruptor;
import org.slf4j.MDC;

import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

publicclass SensitiveDataMaskingAppender extends AppenderBase<ILoggingEvent> {

    // 正则表达式模式用于匹配身份证号码
    privatestaticfinal Pattern ID_CARD_PATTERN = Pattern.compile("\\d{15}(\\d{2}[A-Za-z])?");
    // 正则表达式模式用于匹配手机号码
    privatestaticfinal Pattern PHONE_NUMBER_PATTERN = Pattern.compile("(\\+86)?(1[3-9]\\d{9})");

    private RingBuffer<Event> ringBuffer;

    @Override
    public void start() {
        super.start();

        // 创建事件工厂
        EventFactory<Event> factory = Event::new;
        // 设置环形缓冲区大小,必须是2的幂
        int bufferSize = 1024;
        // 使用缓存线程池
        Executor executor = Executors.newCachedThreadPool();
        // 创建Disruptor实例
        Disruptor<Event> disruptor = new Disruptor<>(factory, bufferSize, executor,
                ProducerType.MULTI, new BusySpinWaitStrategy());
        // 设置事件处理器
        disruptor.handleEventsWith(new EventHandler<Event>() {
            @Override
            public void onEvent(Event event, long sequence, boolean endOfBatch) throws Exception {
                // 脱敏日志消息
                String logMessage = maskSensitiveData(event.getLogMessage());
                // 打印脱敏后的日志消息到控制台
                System.out.println(logMessage);
            }
        });
        // 获取RingBuffer
        ringBuffer = disruptor.getRingBuffer();
        // 启动Disruptor
        disruptor.start();
    }

    @Override
    protected void append(ILoggingEvent eventObject) {
        // 获取下一个序列号
        long sequence = ringBuffer.next(); 
        try {
            // 根据序列号获取事件对象
            Event event = ringBuffer.get(sequence); 
            // 设置日志消息
            event.setLogMessage(eventObject.getMessage()); 
        } finally {
            // 发布事件
            ringBuffer.publish(sequence);
        }
    }

    /**
     * 脱敏日志消息中的敏感信息
     * @param message 日志消息
     * @return 脱敏后的日志消息
     */
    private String maskSensitiveData(String message) {
        Matcher idCardMatcher = ID_CARD_PATTERN.matcher(message);
        while (idCardMatcher.find()) {
            // 替换身份证号码中间部分为星号
            String maskedIdCard = idCardMatcher.group().substring(0, 6) + "********" + idCardMatcher.group().substring(14);
            message = message.replace(idCardMatcher.group(), maskedIdCard);
        }

        Matcher phoneNumberMatcher = PHONE_NUMBER_PATTERN.matcher(message);
        while (phoneNumberMatcher.find()) {
            // 替换手机号码中间部分为星号
            String maskedPhoneNumber = phoneNumberMatcher.group().substring(0, 3) + "****" + phoneNumberMatcher.group().substring(7);
            message = message.replace(phoneNumberMatcher.group(), maskedPhoneNumber);
        }

        return message;
    }

    // 定义事件类
    privatestaticclass Event {
        private String logMessage;

        public String getLogMessage() {
            return logMessage;
        }

        public void setLogMessage(String logMessage) {
            this.logMessage = logMessage;
        }
    }
}

配置Logback使用自定义Appender

在src/main/resources/logback-spring.xml文件中配置自定义appender:

<configuration>
    <!-- 自定义Appender配置 -->
    <appender name="SENSITIVE_MASKING_APPENDER" class="com.example.demo.logging.SensitiveDataMaskingAppender">
    </appender>

    <!-- 根Logger配置 -->
    <root level="info">
        <appender-ref ref="SENSITIVE_MASKING_APPENDER"/>
    </root>
</configuration>

创建Controller、Service和Repository层

Controller层

创建一个简单的控制器来测试日志记录功能。

package com.example.demo.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
publicclass UserController {

    // 获取日志记录器
    privatestaticfinal Logger logger = LoggerFactory.getLogger(UserController.class);

    /**
     * 处理/user请求,记录用户信息并返回响应
     * @param idCard 用户身份证号码
     * @param phoneNumber 用户手机号码
     * @return 响应字符串
     */
    @GetMapping("/user")
    public String getUserInfo(@RequestParam String idCard, @RequestParam String phoneNumber) {
        // 记录用户信息到日志
        logger.info("User Info - ID Card: {}, Phone Number: {}", idCard, phoneNumber);
        return"User info logged";
    }
}

启动类

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

测试

curl "http://localhost:8080/user?idCard=123456123456123456&phnotallow=13800138000"

控制台日志

User Info - ID Card: 123456********56, Phone Number: 138****8000
责任编辑:武晓燕 来源: Java知识日历
相关推荐

2024-09-05 08:58:37

2023-10-09 07:37:01

2023-10-27 08:46:34

DFA算法工具

2025-02-14 09:07:35

2024-12-24 08:44:55

ActiveMQRabbitMQ交换机

2023-06-06 08:51:06

2021-10-28 07:56:52

多线程日志系统嵌入式开发

2025-03-03 07:30:00

SpringBootJGraphT网络建模

2025-02-28 08:40:28

ZooKeeperSpringBoot计费系统

2022-07-08 09:01:36

logback日志异常

2023-03-30 08:11:52

Spring加解密连接池

2024-02-05 13:39:00

隐私数据脱敏

2020-04-23 15:08:41

SpringBootMyCatJava

2024-11-15 10:39:11

2023-08-30 08:43:42

asyncioaiohttp

2024-01-10 18:49:47

2024-05-06 08:45:25

Spring分布式日志

2017-05-11 20:20:59

JavascriptPromiseWeb

2012-12-28 14:32:34

Android开发Handler异步处理

2022-04-28 07:31:41

Springkafka数据量
点赞
收藏

51CTO技术栈公众号