淘宝返利软件的日志审计系统:Java Logback+ELK Stack实现操作日志的可追溯与可视化分析

淘宝返利软件的日志审计系统:Java Logback+ELK Stack实现操作日志的可追溯与可视化分析

大家好,我是 微赚淘客系统3.0 的研发者省赚客!

在淘宝返利类软件中,用户提现、订单绑定、佣金结算等关键操作必须具备完整、不可篡改的日志记录,以满足安全审计与问题回溯需求。我们基于 Java 技术栈,采用 Logback 作为日志框架,结合 ELK(Elasticsearch + Logstash + Kibana)构建集中式日志审计系统,实现结构化日志采集、存储与可视化分析。

日志结构化设计

首先定义统一的操作日志模型,确保字段语义清晰:

java 复制代码
package juwatech.cn.log.model;

import com.fasterxml.jackson.annotation.JsonFormat;
import java.time.LocalDateTime;

public class AuditLog {
    private String traceId;           // 全链路追踪ID
    private String userId;            // 操作用户ID
    private String action;            // 操作类型,如 "WITHDRAW_SUBMIT"
    private String resourceId;        // 关联资源ID,如订单号
    private String clientIp;          // 客户端IP
    private String userAgent;         // 客户端标识
    private String status;            // SUCCESS/FAIL
    private String errorMessage;      // 错误详情(可选)
    
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime timestamp;

    // 省略 getter/setter
}

Logback 配置输出 JSON 格式日志

logback-spring.xml 中配置 net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder,将日志直接输出为 JSON:

xml 复制代码
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
            <providers>
                <timestamp/>
                <logLevel/>
                <loggerName/>
                <message/>
                <arguments/>
                <mdc/> <!-- 支持 MDC 注入 traceId、userId 等 -->
                <stackTrace/>
            </providers>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>

MDC 上下文注入关键字段

在请求入口处通过拦截器注入用户ID、TraceID等信息到 MDC:

java 复制代码
package juwatech.cn.log.interceptor;

import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;

@Component
public class AuditLogInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String traceId = UUID.randomUUID().toString().replace("-", "");
        String userId = request.getHeader("X-User-ID"); // 由网关注入
        String clientIp = getClientIp(request);

        MDC.put("traceId", traceId);
        MDC.put("userId", userId != null ? userId : "anonymous");
        MDC.put("clientIp", clientIp);
        MDC.put("userAgent", request.getHeader("User-Agent"));

        return true;
    }

    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty()) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        MDC.clear();
    }
}

注册拦截器:

java 复制代码
package juwatech.cn.config;

import juwatech.cn.log.interceptor.AuditLogInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuditLogInterceptor())
                .addPathPatterns("/api/**");
    }
}

业务层记录审计日志

在关键服务方法中记录结构化日志:

java 复制代码
package juwatech.cn.service;

import juwatech.cn.log.model.AuditLog;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

@Service
public class WithdrawService {

    private static final Logger auditLogger = LoggerFactory.getLogger("AUDIT_LOG");
    private final ObjectMapper objectMapper = new ObjectMapper();

    public void submitWithdraw(String userId, String orderId, double amount) {
        try {
            // 执行提现逻辑
            processWithdraw(userId, orderId, amount);

            AuditLog log = new AuditLog();
            log.setAction("WITHDRAW_SUBMIT");
            log.setUserId(userId);
            log.setResourceId(orderId);
            log.setStatus("SUCCESS");
            log.setTimestamp(java.time.LocalDateTime.now());

            auditLogger.info(objectMapper.writeValueAsString(log));
        } catch (Exception e) {
            AuditLog log = new AuditLog();
            log.setAction("WITHDRAW_SUBMIT");
            log.setUserId(userId);
            log.setResourceId(orderId);
            log.setStatus("FAIL");
            log.setErrorMessage(e.getMessage());
            log.setTimestamp(java.time.LocalDateTime.now());

            auditLogger.warn(objectMapper.writeValueAsString(log));
            throw e;
        }
    }

    private void processWithdraw(String userId, String orderId, double amount) {
        // 实际业务逻辑
    }
}

Logstash 配置解析与转发

Logstash 配置文件 logstash.conf 如下,从 Filebeat 或直接从 Docker 日志读取并写入 Elasticsearch:

conf 复制代码
input {
  beats {
    port => 5044
  }
}

filter {
  json {
    source => "message"
    target => "log"
  }
  date {
    match => ["[log][timestamp]", "yyyy-MM-dd HH:mm:ss"]
    target => "@timestamp"
  }
}

output {
  elasticsearch {
    hosts => ["http://elasticsearch.juwatech.cn:9200"]
    index => "juwatech-audit-%{+YYYY.MM.dd}"
  }
}

Kibana 可视化看板

在 Kibana 中创建索引模式 juwatech-audit-*,并基于以下字段构建看板:

  • log.action 统计操作分布
  • log.status 监控失败率
  • 通过 log.traceId 追踪全链路
  • 设置告警规则:当 WITHDRAW_SUBMIT 失败率 > 1% 时触发通知

日志安全与合规

所有审计日志禁止删除,Elasticsearch 索引设置生命周期策略(ILM)保留180天,并开启 HTTPS 与 Basic Auth 访问控制。同时,敏感字段(如手机号)在业务层脱敏后再记录。

本文著作权归 微赚淘客系统3.0 研发团队,转载请注明出处!

相关推荐
铁蛋AI编程实战2 小时前
Falcon-H1-Tiny 微型 LLM 部署指南:100M 参数也能做复杂推理,树莓派 / 手机都能跑
java·人工智能·python·智能手机
yangminlei2 小时前
Spring Boot 4.0.1新特性概览
java·spring boot
C+-C资深大佬2 小时前
C++多态
java·jvm·c++
WJX_KOI2 小时前
保姆级教程:Apache Seatunnel CDC(standalone 模式)部署 MySQL CDC、PostgreSQL CDC 及使用方法
java·大数据·mysql·postgresql·big data·etl
今天你TLE了吗2 小时前
JVM学习笔记:第一章——JVM&Java体系结构
java·jvm·笔记·学习
毕设源码-朱学姐2 小时前
【开题答辩全过程】以 基于JAVAweb的影视创作论坛系统为例,包含答辩的问题和答案
java
葡萄城技术团队2 小时前
GcExcel V9.0 新特性解密:VALUETOTEXT/ARRAYTOTEXT 双函数,让数据文本转换更精准高效
java
她说..2 小时前
策略模式+工厂模式实现订单校验功能
java·spring boot·java-ee·简单工厂模式·策略模式
短剑重铸之日2 小时前
《设计模式》第五篇:策略模式
java·后端·设计模式·策略模式