Disable auditing infrastructure by default
Prior to this commit, the audit auto-configuration provided an `InMemoryAuditEventRepository` bean. This commit changes the auto-config so that an `AuditEventRepository` is not provided and instead the auto-config is conditional on the presence of a `AuditEventRepository` bean. This is done to encourage the use of a custom implementation of `AuditEventRepository` since the in-memory one is quite limited and not suitable for production. A flag is available if the auto-configuration needs to be turned off even in the presence of a bean. Closes gh-16110
This commit is contained in:
parent
e2b15c3f2a
commit
07d6eb6397
|
@ -16,10 +16,8 @@
|
||||||
|
|
||||||
package org.springframework.boot.actuate.autoconfigure.audit;
|
package org.springframework.boot.actuate.autoconfigure.audit;
|
||||||
|
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
|
||||||
import org.springframework.boot.actuate.audit.AuditEvent;
|
import org.springframework.boot.actuate.audit.AuditEvent;
|
||||||
import org.springframework.boot.actuate.audit.AuditEventRepository;
|
import org.springframework.boot.actuate.audit.AuditEventRepository;
|
||||||
import org.springframework.boot.actuate.audit.InMemoryAuditEventRepository;
|
|
||||||
import org.springframework.boot.actuate.audit.listener.AbstractAuditListener;
|
import org.springframework.boot.actuate.audit.listener.AbstractAuditListener;
|
||||||
import org.springframework.boot.actuate.audit.listener.AuditListener;
|
import org.springframework.boot.actuate.audit.listener.AuditListener;
|
||||||
import org.springframework.boot.actuate.security.AbstractAuthenticationAuditListener;
|
import org.springframework.boot.actuate.security.AbstractAuthenticationAuditListener;
|
||||||
|
@ -27,8 +25,10 @@ import org.springframework.boot.actuate.security.AbstractAuthorizationAuditListe
|
||||||
import org.springframework.boot.actuate.security.AuthenticationAuditListener;
|
import org.springframework.boot.actuate.security.AuthenticationAuditListener;
|
||||||
import org.springframework.boot.actuate.security.AuthorizationAuditListener;
|
import org.springframework.boot.actuate.security.AuthorizationAuditListener;
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@ -40,13 +40,15 @@ import org.springframework.context.annotation.Configuration;
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ConditionalOnBean(AuditEventRepository.class)
|
||||||
|
@ConditionalOnProperty(prefix = "management.auditevents", name = "enabled",
|
||||||
|
matchIfMissing = true)
|
||||||
public class AuditAutoConfiguration {
|
public class AuditAutoConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean(AbstractAuditListener.class)
|
@ConditionalOnMissingBean(AbstractAuditListener.class)
|
||||||
public AuditListener auditListener(
|
public AuditListener auditListener(AuditEventRepository auditEventRepository) {
|
||||||
ObjectProvider<AuditEventRepository> auditEventRepository) throws Exception {
|
return new AuditListener(auditEventRepository);
|
||||||
return new AuditListener(auditEventRepository.getIfAvailable());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@ -65,15 +67,4 @@ public class AuditAutoConfiguration {
|
||||||
return new AuthorizationAuditListener();
|
return new AuthorizationAuditListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
|
||||||
@ConditionalOnMissingBean(AuditEventRepository.class)
|
|
||||||
protected static class AuditEventRepositoryConfiguration {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public InMemoryAuditEventRepository auditEventRepository() throws Exception {
|
|
||||||
return new InMemoryAuditEventRepository();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,12 @@
|
||||||
"description": "Whether to skip SSL verification for Cloud Foundry actuator endpoint security calls.",
|
"description": "Whether to skip SSL verification for Cloud Foundry actuator endpoint security calls.",
|
||||||
"defaultValue": false
|
"defaultValue": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "management.auditevents.enabled",
|
||||||
|
"type": "java.lang.Boolean",
|
||||||
|
"description": "Whether to enable storage of audit events.",
|
||||||
|
"defaultValue": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "management.health.cassandra.enabled",
|
"name": "management.health.cassandra.enabled",
|
||||||
"type": "java.lang.Boolean",
|
"type": "java.lang.Boolean",
|
||||||
|
|
|
@ -22,12 +22,14 @@ import org.springframework.boot.actuate.audit.AuditEvent;
|
||||||
import org.springframework.boot.actuate.audit.AuditEventRepository;
|
import org.springframework.boot.actuate.audit.AuditEventRepository;
|
||||||
import org.springframework.boot.actuate.audit.InMemoryAuditEventRepository;
|
import org.springframework.boot.actuate.audit.InMemoryAuditEventRepository;
|
||||||
import org.springframework.boot.actuate.audit.listener.AbstractAuditListener;
|
import org.springframework.boot.actuate.audit.listener.AbstractAuditListener;
|
||||||
|
import org.springframework.boot.actuate.audit.listener.AuditListener;
|
||||||
import org.springframework.boot.actuate.security.AbstractAuthenticationAuditListener;
|
import org.springframework.boot.actuate.security.AbstractAuthenticationAuditListener;
|
||||||
import org.springframework.boot.actuate.security.AbstractAuthorizationAuditListener;
|
import org.springframework.boot.actuate.security.AbstractAuthorizationAuditListener;
|
||||||
import org.springframework.boot.actuate.security.AuthenticationAuditListener;
|
import org.springframework.boot.actuate.security.AuthenticationAuditListener;
|
||||||
import org.springframework.boot.actuate.security.AuthorizationAuditListener;
|
import org.springframework.boot.actuate.security.AuthorizationAuditListener;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||||
|
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||||
import org.springframework.context.ApplicationEventPublisher;
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.access.event.AbstractAuthorizationEvent;
|
import org.springframework.security.access.event.AbstractAuthorizationEvent;
|
||||||
|
@ -40,54 +42,71 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Vedran Pavic
|
* @author Vedran Pavic
|
||||||
|
* @author Madhura Bhave
|
||||||
*/
|
*/
|
||||||
public class AuditAutoConfigurationTests {
|
public class AuditAutoConfigurationTests {
|
||||||
|
|
||||||
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||||
|
.withConfiguration(AutoConfigurations.of(AuditAutoConfiguration.class));
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void defaultConfiguration() {
|
public void autoConfigurationIsDisabledByDefault() {
|
||||||
registerAndRefresh(AuditAutoConfiguration.class);
|
this.contextRunner.run((context) -> assertThat(context)
|
||||||
assertThat(this.context.getBean(AuditEventRepository.class)).isNotNull();
|
.doesNotHaveBean(AuditAutoConfiguration.class));
|
||||||
assertThat(this.context.getBean(AuthenticationAuditListener.class)).isNotNull();
|
|
||||||
assertThat(this.context.getBean(AuthorizationAuditListener.class)).isNotNull();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void ownAuditEventRepository() {
|
public void autoConfigurationIsEnabledWhenAuditEventRepositoryBeanPresent() {
|
||||||
registerAndRefresh(CustomAuditEventRepositoryConfiguration.class,
|
this.contextRunner
|
||||||
AuditAutoConfiguration.class);
|
.withUserConfiguration(CustomAuditEventRepositoryConfiguration.class)
|
||||||
assertThat(this.context.getBean(AuditEventRepository.class))
|
.run((context) -> {
|
||||||
.isInstanceOf(TestAuditEventRepository.class);
|
assertThat(context.getBean(AuditEventRepository.class)).isNotNull();
|
||||||
|
assertThat(context.getBean(AuthenticationAuditListener.class))
|
||||||
|
.isNotNull();
|
||||||
|
assertThat(context.getBean(AuthorizationAuditListener.class))
|
||||||
|
.isNotNull();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void ownAuthenticationAuditListener() {
|
public void ownAuthenticationAuditListener() {
|
||||||
registerAndRefresh(CustomAuthenticationAuditListenerConfiguration.class,
|
this.contextRunner
|
||||||
AuditAutoConfiguration.class);
|
.withUserConfiguration(CustomAuditEventRepositoryConfiguration.class)
|
||||||
assertThat(this.context.getBean(AbstractAuthenticationAuditListener.class))
|
.withUserConfiguration(
|
||||||
.isInstanceOf(TestAuthenticationAuditListener.class);
|
CustomAuthenticationAuditListenerConfiguration.class)
|
||||||
|
.run((context) -> assertThat(
|
||||||
|
context.getBean(AbstractAuthenticationAuditListener.class))
|
||||||
|
.isInstanceOf(TestAuthenticationAuditListener.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void ownAuthorizationAuditListener() {
|
public void ownAuthorizationAuditListener() {
|
||||||
registerAndRefresh(CustomAuthorizationAuditListenerConfiguration.class,
|
this.contextRunner
|
||||||
AuditAutoConfiguration.class);
|
.withUserConfiguration(CustomAuditEventRepositoryConfiguration.class)
|
||||||
assertThat(this.context.getBean(AbstractAuthorizationAuditListener.class))
|
.withUserConfiguration(
|
||||||
.isInstanceOf(TestAuthorizationAuditListener.class);
|
CustomAuthorizationAuditListenerConfiguration.class)
|
||||||
|
.run((context) -> assertThat(
|
||||||
|
context.getBean(AbstractAuthorizationAuditListener.class))
|
||||||
|
.isInstanceOf(TestAuthorizationAuditListener.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void ownAuditListener() {
|
public void ownAuditListener() {
|
||||||
registerAndRefresh(CustomAuditListenerConfiguration.class,
|
this.contextRunner
|
||||||
AuditAutoConfiguration.class);
|
.withUserConfiguration(CustomAuditEventRepositoryConfiguration.class)
|
||||||
assertThat(this.context.getBean(AbstractAuditListener.class))
|
.withUserConfiguration(CustomAuditListenerConfiguration.class)
|
||||||
.isInstanceOf(TestAuditListener.class);
|
.run((context) -> assertThat(context.getBean(AbstractAuditListener.class))
|
||||||
|
.isInstanceOf(TestAuditListener.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerAndRefresh(Class<?>... annotatedClasses) {
|
@Test
|
||||||
this.context.register(annotatedClasses);
|
public void backsOffWhenDisabled() {
|
||||||
this.context.refresh();
|
this.contextRunner
|
||||||
|
.withUserConfiguration(CustomAuditEventRepositoryConfiguration.class)
|
||||||
|
.withPropertyValues("management.auditevents.enabled=false")
|
||||||
|
.run((context) -> assertThat(context).doesNotHaveBean(AuditListener.class)
|
||||||
|
.doesNotHaveBean(AuthenticationAuditListener.class)
|
||||||
|
.doesNotHaveBean(AuthorizationAuditListener.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
|
|
@ -19,8 +19,11 @@ package org.springframework.boot.actuate.autoconfigure.audit;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.boot.actuate.audit.AuditEventsEndpoint;
|
import org.springframework.boot.actuate.audit.AuditEventsEndpoint;
|
||||||
|
import org.springframework.boot.actuate.audit.InMemoryAuditEventRepository;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
@ -38,14 +41,24 @@ public class AuditEventsEndpointAutoConfigurationTests {
|
||||||
AuditEventsEndpointAutoConfiguration.class));
|
AuditEventsEndpointAutoConfiguration.class));
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void runShouldHaveEndpointBean() {
|
public void runWhenRepositoryBeanAvailableShouldHaveEndpointBean() {
|
||||||
this.contextRunner
|
this.contextRunner
|
||||||
|
.withUserConfiguration(CustomAuditEventRepositoryConfiguration.class)
|
||||||
.withPropertyValues(
|
.withPropertyValues(
|
||||||
"management.endpoints.web.exposure.include=auditevents")
|
"management.endpoints.web.exposure.include=auditevents")
|
||||||
.run((context) -> assertThat(context)
|
.run((context) -> assertThat(context)
|
||||||
.hasSingleBean(AuditEventsEndpoint.class));
|
.hasSingleBean(AuditEventsEndpoint.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void endpointBacksOffWhenRepositoryNotAvailable() {
|
||||||
|
this.contextRunner
|
||||||
|
.withPropertyValues(
|
||||||
|
"management.endpoints.web.exposure.include=auditevents")
|
||||||
|
.run((context) -> assertThat(context)
|
||||||
|
.doesNotHaveBean(AuditEventsEndpoint.class));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void runWhenNotExposedShouldNotHaveEndpointBean() {
|
public void runWhenNotExposedShouldNotHaveEndpointBean() {
|
||||||
this.contextRunner.run((context) -> assertThat(context)
|
this.contextRunner.run((context) -> assertThat(context)
|
||||||
|
@ -55,10 +68,21 @@ public class AuditEventsEndpointAutoConfigurationTests {
|
||||||
@Test
|
@Test
|
||||||
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpoint() {
|
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpoint() {
|
||||||
this.contextRunner
|
this.contextRunner
|
||||||
|
.withUserConfiguration(CustomAuditEventRepositoryConfiguration.class)
|
||||||
.withPropertyValues("management.endpoint.auditevents.enabled:false")
|
.withPropertyValues("management.endpoint.auditevents.enabled:false")
|
||||||
.withPropertyValues("management.endpoints.web.exposure.include=*")
|
.withPropertyValues("management.endpoints.web.exposure.include=*")
|
||||||
.run((context) -> assertThat(context)
|
.run((context) -> assertThat(context)
|
||||||
.doesNotHaveBean(AuditEventsEndpoint.class));
|
.doesNotHaveBean(AuditEventsEndpoint.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
public static class CustomAuditEventRepositoryConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public InMemoryAuditEventRepository testAuditEventRepository() {
|
||||||
|
return new InMemoryAuditEventRepository();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import javax.management.ReflectionException;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.actuate.audit.InMemoryAuditEventRepository;
|
||||||
import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration;
|
import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration;
|
||||||
import org.springframework.boot.actuate.autoconfigure.endpoint.jmx.JmxEndpointAutoConfiguration;
|
import org.springframework.boot.actuate.autoconfigure.endpoint.jmx.JmxEndpointAutoConfiguration;
|
||||||
import org.springframework.boot.actuate.autoconfigure.health.HealthIndicatorAutoConfiguration;
|
import org.springframework.boot.actuate.autoconfigure.health.HealthIndicatorAutoConfiguration;
|
||||||
|
@ -53,7 +54,8 @@ public class JmxEndpointIntegrationTests {
|
||||||
EndpointAutoConfiguration.class, JmxEndpointAutoConfiguration.class,
|
EndpointAutoConfiguration.class, JmxEndpointAutoConfiguration.class,
|
||||||
HealthIndicatorAutoConfiguration.class,
|
HealthIndicatorAutoConfiguration.class,
|
||||||
HttpTraceAutoConfiguration.class))
|
HttpTraceAutoConfiguration.class))
|
||||||
.withUserConfiguration(HttpTraceRepositoryConfiguration.class)
|
.withUserConfiguration(HttpTraceRepositoryConfiguration.class,
|
||||||
|
AuditEventRepositoryConfiguration.class)
|
||||||
.withPropertyValues("spring.jmx.enabled=true").withConfiguration(
|
.withPropertyValues("spring.jmx.enabled=true").withConfiguration(
|
||||||
AutoConfigurations.of(EndpointAutoConfigurationClasses.ALL));
|
AutoConfigurations.of(EndpointAutoConfigurationClasses.ALL));
|
||||||
|
|
||||||
|
@ -152,4 +154,14 @@ public class JmxEndpointIntegrationTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
public static class AuditEventRepositoryConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public InMemoryAuditEventRepository auditEventRepository() {
|
||||||
|
return new InMemoryAuditEventRepository();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.actuate.audit.InMemoryAuditEventRepository;
|
||||||
import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration;
|
import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration;
|
||||||
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration;
|
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration;
|
||||||
import org.springframework.boot.actuate.autoconfigure.health.HealthIndicatorAutoConfiguration;
|
import org.springframework.boot.actuate.autoconfigure.health.HealthIndicatorAutoConfiguration;
|
||||||
|
@ -83,7 +84,8 @@ public class WebMvcEndpointExposureIntegrationTests {
|
||||||
AutoConfigurations.of(EndpointAutoConfigurationClasses.ALL))
|
AutoConfigurations.of(EndpointAutoConfigurationClasses.ALL))
|
||||||
.withUserConfiguration(CustomMvcEndpoint.class,
|
.withUserConfiguration(CustomMvcEndpoint.class,
|
||||||
CustomServletEndpoint.class,
|
CustomServletEndpoint.class,
|
||||||
HttpTraceRepositoryConfiguration.class)
|
HttpTraceRepositoryConfiguration.class,
|
||||||
|
AuditEventRepositoryConfiguration.class)
|
||||||
.withPropertyValues("server.port:0");
|
.withPropertyValues("server.port:0");
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -229,4 +231,14 @@ public class WebMvcEndpointExposureIntegrationTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
public static class AuditEventRepositoryConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public InMemoryAuditEventRepository auditEventRepository() {
|
||||||
|
return new InMemoryAuditEventRepository();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2200,12 +2200,23 @@ maximum size for the "Metaspace", you could add an additional `tag=id:Metaspace`
|
||||||
Once Spring Security is in play, Spring Boot Actuator has a flexible audit framework that
|
Once Spring Security is in play, Spring Boot Actuator has a flexible audit framework that
|
||||||
publishes events (by default, "`authentication success`", "`failure`" and
|
publishes events (by default, "`authentication success`", "`failure`" and
|
||||||
"`access denied`" exceptions). This feature can be very useful for reporting and for
|
"`access denied`" exceptions). This feature can be very useful for reporting and for
|
||||||
implementing a lock-out policy based on authentication failures. To customize published
|
implementing a lock-out policy based on authentication failures.
|
||||||
security events, you can provide your own implementations of
|
|
||||||
|
Auditing can be enabled by providing a bean of type `AuditEventRepository` in your application's
|
||||||
|
configuration. For convenience, Spring Boot offers an `InMemoryAuditEventRepository`.
|
||||||
|
`InMemoryAuditEventRepository` has limited capabilities and we recommend using it only for development
|
||||||
|
environments. For production environments, consider creating your own alternative `AuditEventRepository`
|
||||||
|
implementation.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[production-ready-auditing-custom]]
|
||||||
|
=== Custom Auditing
|
||||||
|
To customize published security events, you can provide your own implementations of
|
||||||
`AbstractAuthenticationAuditListener` and `AbstractAuthorizationAuditListener`.
|
`AbstractAuthenticationAuditListener` and `AbstractAuthorizationAuditListener`.
|
||||||
|
|
||||||
You can also use the audit services for your own business events. To do so, either inject
|
You can also use the audit services for your own business events. To do so, either inject
|
||||||
the existing `AuditEventRepository` into your own components and use that directly or
|
the `AuditEventRepository` bean into your own components and use that directly or
|
||||||
publish an `AuditApplicationEvent` with the Spring `ApplicationEventPublisher` (by
|
publish an `AuditApplicationEvent` with the Spring `ApplicationEventPublisher` (by
|
||||||
implementing `ApplicationEventPublisherAware`).
|
implementing `ApplicationEventPublisherAware`).
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue