package com.vincent.rsf.httpaudit.config; import com.vincent.rsf.httpaudit.mapper.HttpAuditLogMapper; import com.vincent.rsf.httpaudit.mapper.HttpAuditConfigMapper; import com.vincent.rsf.httpaudit.mapper.HttpAuditRuleMapper; import com.vincent.rsf.httpaudit.props.HttpAuditProperties; import com.vincent.rsf.httpaudit.service.HttpAuditAsyncRecorder; import com.vincent.rsf.httpaudit.service.HttpAuditCleanupService; import com.vincent.rsf.httpaudit.service.HttpAuditDbConfigService; import com.vincent.rsf.httpaudit.service.HttpAuditLogCrudService; import com.vincent.rsf.httpaudit.service.HttpAuditLogCrudServiceImpl; import com.vincent.rsf.httpaudit.service.HttpAuditLogSink; import com.vincent.rsf.httpaudit.service.HttpAuditOutboundRecorder; import com.vincent.rsf.httpaudit.service.HttpAuditRuleService; import com.vincent.rsf.httpaudit.service.HttpAuditRuleServiceImpl; import com.vincent.rsf.httpaudit.service.HttpAuditSysConfigService; import com.vincent.rsf.httpaudit.service.HttpAuditSysConfigServiceImpl; import com.vincent.rsf.httpaudit.service.MysqlHttpAuditLogSink; import com.vincent.rsf.httpaudit.service.OpenSearchHttpAuditLogSink; import com.vincent.rsf.httpaudit.web.HttpAuditFilter; import com.vincent.rsf.httpaudit.web.OutboundHttpAuditInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.opensearch.client.RestClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.core.Ordered; import org.springframework.core.env.Environment; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; /** * 引入 rsf-http-audit 即生效(可 http-audit.enabled=false 关闭) */ @Configuration @EnableAsync @EnableScheduling @EnableConfigurationProperties(HttpAuditProperties.class) @ConditionalOnProperty(prefix = "http-audit", name = "enabled", havingValue = "true", matchIfMissing = true) @MapperScan("com.vincent.rsf.httpaudit.mapper") @Import({HttpAuditAdminApiAutoConfiguration.class, HttpAuditOpenUiAutoConfiguration.class, HttpAuditOpenSearchConfiguration.class}) public class HttpAuditAutoConfiguration { private static final Logger log = LoggerFactory.getLogger(HttpAuditAutoConfiguration.class); @Bean public HttpAuditSysConfigService httpAuditSysConfigService(HttpAuditConfigMapper httpAuditConfigMapper) { return new HttpAuditSysConfigServiceImpl(httpAuditConfigMapper); } @Bean public HttpAuditLogCrudService httpAuditLogCrudService(HttpAuditLogMapper httpAuditLogMapper) { return new HttpAuditLogCrudServiceImpl(httpAuditLogMapper); } @Bean public HttpAuditRuleService httpAuditRuleService(HttpAuditRuleMapper mapper, HttpAuditProperties props) { return new HttpAuditRuleServiceImpl(mapper, props); } @Bean public HttpAuditAsyncRecorder httpAuditAsyncRecorder( HttpAuditProperties props, HttpAuditLogMapper httpAuditLogMapper, @Autowired(required = false) OpenSearchHttpAuditLogSink openSearchHttpAuditLogSink) { List sinks = new ArrayList<>(); if (props.usesMysqlLogStorage()) { sinks.add(new MysqlHttpAuditLogSink(httpAuditLogMapper)); } if (props.usesOpenSearchLogStorage()) { if (openSearchHttpAuditLogSink == null) { log.warn("http_audit_warn code=opensearch_sink_missing log_storage_mode={}", props.resolveLogStorageMode()); } else { sinks.add(openSearchHttpAuditLogSink); } } if (sinks.isEmpty()) { log.warn("http_audit_warn code=no_log_sinks log_storage_mode={}", props.resolveLogStorageMode()); } return new HttpAuditAsyncRecorder(sinks); } @Bean public HttpAuditCleanupService httpAuditCleanupService( HttpAuditLogMapper httpAuditLogMapper, HttpAuditProperties props, @Autowired(required = false) @Qualifier("httpAuditOpenSearchRestClient") RestClient httpAuditOpenSearchRestClient) { return new HttpAuditCleanupService(httpAuditLogMapper, props, httpAuditOpenSearchRestClient); } @Bean public HttpAuditDbConfigService httpAuditDbConfigService(HttpAuditConfigMapper httpAuditConfigMapper) { return new HttpAuditDbConfigService(httpAuditConfigMapper); } @Bean public HttpAuditOutboundRecorder httpAuditOutboundRecorder( HttpAuditAsyncRecorder recorder, HttpAuditProperties props, Environment env, HttpAuditRuleService httpAuditRuleService) { return new HttpAuditOutboundRecorder(recorder, props, env, httpAuditRuleService); } @Bean public OutboundHttpAuditInterceptor outboundHttpAuditInterceptor(HttpAuditOutboundRecorder httpAuditOutboundRecorder) { return new OutboundHttpAuditInterceptor(httpAuditOutboundRecorder); } @Bean public HttpAuditRestTemplateBeanPostProcessor httpAuditRestTemplateBeanPostProcessor( OutboundHttpAuditInterceptor outboundHttpAuditInterceptor) { return new HttpAuditRestTemplateBeanPostProcessor(outboundHttpAuditInterceptor); } @Bean(name = "httpAuditExecutor") public Executor httpAuditExecutor() { ThreadPoolTaskExecutor ex = new ThreadPoolTaskExecutor(); ex.setCorePoolSize(2); ex.setMaxPoolSize(8); ex.setQueueCapacity(1000); ex.setThreadNamePrefix("http-audit-"); ex.initialize(); return ex; } @Bean public FilterRegistrationBean httpAuditFilterRegistration( HttpAuditAsyncRecorder recorder, HttpAuditProperties props, Environment env, HttpAuditRuleService httpAuditRuleService) { HttpAuditFilter filter = new HttpAuditFilter(recorder, props, env, httpAuditRuleService); FilterRegistrationBean reg = new FilterRegistrationBean<>(); reg.setFilter(filter); reg.addUrlPatterns("/*"); reg.setOrder(Ordered.HIGHEST_PRECEDENCE + 50); return reg; } }