Spring Boot:在AuditApplicationEvent侦听器中获取查询字符串参数和请求主体

时间:2018-06-29 18:16:07

标签: spring-boot java-8 auditing http-trace

Spring Boot REST应用程序在这里。我正在尝试配置Spring Boot请求审核以记录任何资源/控制器收到的每个HTTP请求的以下信息:

  1. 我需要在日志中查看客户端请求的确切HTTP URL(路径),包括HTTP方法和任何查询字符串参数;和
  2. 如果有请求正文(例如POST或PUT),我还需要在日志中查看该正文的内容

到目前为止我最大的尝试:

@Component
public class MyAppAuditor {
    private Logger logger;

    @EventListener
    public void handleAuditEvent(AuditApplicationEvent auditApplicationEvent) {
        logger.info(auditApplicationEvent.auditEvent);
    }
}

public class AuditingTraceRepository implements TraceRepository {
    @Autowired
    private ApplicationEventPublisher applicationEventPublisher

    @Override
    List<Trace> findAll() {
        throw new UnsupportedOperationException("We don't expose trace information via /trace!");
    }

    @Override
    void add(Map<String, Object> traceInfo) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        AuditEvent traceRequestEvent = new AuditEvent(new Date(), "SomeUser", 'http.request.trace', traceInfo);
        AuditApplicationEvent traceRequestAppEvent = new AuditApplicationEvent(traceRequestEvent);

        applicationEventPublisher.publishEvent(traceRequestAppEvent);
    }
}

但是在运行时,如果我使用以下curl命令:

curl -i -H "Content-Type: application/json" -X GET 'http://localhost:9200/v1/data/profiles?continent=NA&country=US&isMale=0&height=1.5&dob=range('1980-01-01','1990-01-01')'

然后,我仅看到以下日志消息(其中MyAppAuditor发送审核事件):

{ "timestamp" : "14:09:50.516", "thread" : "qtp1293252487-17", "level" : "INFO", "logger" : "com.myapp.ws.shared.auditing.MyAppAuditor", "message" : {"timestamp":"2018-06-29T18:09:50+0000","principal":"SomeUser","type":"http.request.trace","data":{"method":"GET","path":"/v1/data/profiles","headers":{"request":{"User-Agent":"curl/7.54.0","Host":"localhost:9200","Accept":"*/*","Content-Type":"application/json"},"response":{"X-Frame-Options":"DENY","Cache-Control":"no-cache, no-store, max-age=0, must-revalidate","X-Content-Type-Options":"nosniff","Pragma":"no-cache","Expires":"0","X-XSS-Protection":"1; mode=block","X-Application-Context":"application:9200","Date":"Fri, 29 Jun 2018 18:09:50 GMT","Content-Type":"application/json;charset=utf-8","status":"200"}},"timeTaken":"89"}} }

因此,如您所见,审核员正在选择基本路径(/v1/data/profiles),但未记录任何查询字符串参数。当我点击确实需要请求正文(JSON)的POST或PUT端点时,我也看到类似的请求正文信息缺失。

我需要做什么来配置这些类(或其他Spring类/配置),以便获得所需的请求审核级别?

1 个答案:

答案 0 :(得分:2)

幸运的是,执行器使配置这些Trace事件变得非常容易。

为跟踪信息添加参数

您可以take a look的所有选项。您会注意到默认值(line 42)是:

Include.REQUEST_HEADERS, 
Include.RESPONSE_HEADERS, 
Include.COOKIES, 
Include.ERRORS, 
Include.TIME_TAKEN

因此,您还需要添加Include.PARAMETERS以及跟踪中想要的其他任何内容。要进行配置,该 management.trace.include 有一个配置属性。

因此,要获得所需的内容(即parameters)以及默认值,您将拥有:

management.trace.include = parameters, request-headers, response-headers, cookies, errors, time-taken

为跟踪信息添加请求正文

要获取body,您将不得不将此Bean添加到Context中:

@Component
public class WebRequestTraceFilterWithPayload extends WebRequestTraceFilter {

    public WebRequestTraceFilterWithPayload(TraceRepository repository, TraceProperties properties) {
        super(repository, properties);
    }

    @Override
    protected Map<String, Object> getTrace(HttpServletRequest request) {
        Map<String, Object> trace = super.getTrace(request);

        String body = null;
        try {
            body = request.getReader().lines().collect(Collectors.joining("\n"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        if(body != null) {
            trace.put("body", body);
        }

        return trace;
    }

}

上面的代码将覆盖AutoConfigure'd WebRequestTraceFilter bean(由于它是@ConditionalOnMissingBean,因此会影响您的自定义bean),并从{ {1}},然后将其添加到发布到您的request的{​​{1}}属性中!

摘要

    可以通过Map属性将
  1. 请求参数添加到TraceRepository
  2. 请求正文可以通过创建扩展的TraceRepository trace events从HTTP请求中读取management.trace.include并补充跟踪事件而添加到TraceRepository trace events