Spring Boot Actuator предоставляет возможности аудита для публикации и прослушивания связанных с безопасностью событий в приложении Spring Boot с включенной Spring Security. События по умолчанию — это успешная аутентификация, неудачная аутентификация и отказ в доступе, но они могут быть расширены с помощью пользовательских событий.
Убедитесь, что в вашем проекте включены Spring Boot Security и Actuator
|
1
2
3
4
5
6
7
8
|
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId></dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId></dependency> |
/auditevents точка Actuator /auditevents
По умолчанию /auditevents точка /auditevents включена, поэтому после запуска приложения (и входа в систему с именем user и паролем, указанным в журнале приложения) вы можете видеть текущие события безопасности:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
{ "events": [ { "timestamp": "2017-03-14T22:59:58+0000", "principal": "user", "type": "AUTHENTICATION_FAILURE", "data": { "details": { "remoteAddress": "0:0:0:0:0:0:0:1", "sessionId": null }, "type": "org.springframework.security.authentication.BadCredentialsException", "message": "Bad credentials" } }, { "timestamp": "2017-03-14T23:00:07+0000", "principal": "user", "type": "AUTHENTICATION_SUCCESS", "data": { "details": { "remoteAddress": "0:0:0:0:0:0:0:1", "sessionId": null } } } ]} |
/auditevents точка /auditevents принимает необязательные параметры запроса:
-
pricipal— главное имя -
after— дата после события произошла в следующем формате:yyyy-MM-dd'T'HH:mm:ssZ -
type—typeсобытия (например, AUTHORIZATION_FAILURE, AUTHENTICATION_SUCCESS, AUTHENTICATION_FAILURE, AUTHENTICATION_SWITCH)
Пример запроса:
Реализация конечной точки использует org.springframework.boot.actuate.audit.AuditEventRepository для возврата всех зарегистрированных событий аудита.
- Настроить
/auditeventsконечную точку
Вы можете настроить конечную точку с помощью свойств endpoints.auditevents.* . Например, чтобы изменить путь конечной точки событий аудита, просто используйте свойство endpoints.auditevents.path .
Прослушивание событий аудита безопасности с @EventListener
События безопасности представлены org.springframework.boot.actuate.audit.AuditEvent значения org.springframework.boot.actuate.audit.AuditEvent в приводе. Этот объект содержит метку времени, имя пользователя, тип события и данные события.
Самый простой способ получить уведомление о событиях аудита — подписаться на события org.springframework.boot.actuate.audit.listener.AuditApplicationEvent помощью Spring org.springframework.context.event.EventListener :
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
@Componentpublic class AuditApplicationEventListener { private static final Logger LOG = LoggerFactory.getLogger(AuditApplicationEventListener.class); @EventListener public void onAuditEvent(AuditApplicationEvent event) { AuditEvent actualAuditEvent = event.getAuditEvent(); LOG.info("On audit application event: timestamp: {}, principal: {}, type: {}, data: {}", actualAuditEvent.getTimestamp(), actualAuditEvent.getPrincipal(), actualAuditEvent.getType(), actualAuditEvent.getData() ); }} |
Пример вывода:
|
1
|
2017-03-15 00:44:12.921 INFO 13316 --- [nio-8080-exec-1] p.c.d.s.s.AuditApplicationEventListener : On audit event: timestamp: Wed Mar 15 00:44:12 CET 2017, principal: user, type: AUTHENTICATION_SUCCESS, data: {details=org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null} |
Асинхронные события
@EventListener является синхронным, но если требуется асинхронное поведение, вы можете аннотировать метод прослушивателя событий с помощью @Async и убедиться, что асинхронность включена (например, через @EnableAsync ):
|
01
02
03
04
05
06
07
08
09
10
11
|
@Componentpublic class AuditApplicationEventListener { private static final Logger LOG = LoggerFactory.getLogger(AuditApplicationEventListener.class); @EventListener @Async public void onAuditEvent(AuditApplicationEvent event) { }} |
И конфигурация:
|
1
2
3
4
5
6
7
8
|
@SpringBootApplication@EnableAsyncpublic class Application { public static void main(String[] args) { SpringApplication.run(Application.class); }} |
Прослушивание событий аудита безопасности с AbstractAuditListener
Кроме того, вы можете расширить org.springframework.boot.actuate.audit.listener.AbstractAuditListener и переопределить его org.springframework.boot.actuate.audit.listener.AbstractAuditListener#onAuditEvent :
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
@Componentpublic class AuditEventListener extends AbstractAuditListener { private static final Logger LOG = LoggerFactory.getLogger(AuditEventListener.class); @Override protected void onAuditEvent(AuditEvent event) { LOG.info("On audit event: timestamp: {}, principal: {}, type: {}, data: {}", event.getTimestamp(), event.getPrincipal(), event.getType(), event.getData() ); }} |
Примечание. Никакие события не будут храниться в репозитории событий, поэтому /auditevents точка /auditevents всегда будет возвращать пустой массив. Чтобы это исправить, вы можете внедрить хранилище аудита или расширить его непосредственно из org.springframework.boot.actuate.audit.listener.AuditListener :
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
@Componentpublic class AuditEventListener extends AbstractAuditListener { private static final Logger LOG = LoggerFactory.getLogger(AuditEventListener.class); @Autowired private AuditEventRepository auditEventRepository; @Override protected void onAuditEvent(AuditEvent event) { LOG.info("On audit event: timestamp: {}, principal: {}, type: {}, data: {}", event.getTimestamp(), event.getPrincipal(), event.getType(), event.getData() ); auditEventRepository.add(event); }} |
Публикация собственных аудиторских событий с издателем событий
В приведенном ниже примере издатель событий приложения ( org.springframework.context.ApplicationEventPublisher ) используется для публикации настраиваемого события аудита с типом CUSTOM_AUDIT_EVENT . Новый метод слушателя прослушивает только эти новые события, тогда как предыдущий метод игнорирует их (обратите внимание, что это только пример). Как и любые другие события, пользовательские будут храниться с использованием репозитория событий аудита.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
@Componentpublic class AuditApplicationEventListener { private static final Logger LOG = LoggerFactory.getLogger(AuditApplicationEventListener.class); @Autowired private ApplicationEventPublisher applicationEventPublisher; @EventListener(condition = "#event.auditEvent.type != 'CUSTOM_AUDIT_EVENT'") @Async public void onAuditEvent(AuditApplicationEvent event) { AuditEvent actualAuditEvent = event.getAuditEvent(); LOG.info("On audit application event: timestamp: {}, principal: {}, type: {}, data: {}", actualAuditEvent.getTimestamp(), actualAuditEvent.getPrincipal(), actualAuditEvent.getType(), actualAuditEvent.getData() ); applicationEventPublisher.publishEvent( new AuditApplicationEvent( new AuditEvent(actualAuditEvent.getPrincipal(), "CUSTOM_AUDIT_EVENT") ) ); } @EventListener(condition = "#event.auditEvent.type == 'CUSTOM_AUDIT_EVENT'") public void onCustomAuditEvent(AuditApplicationEvent event) { LOG.info("Handling custom audit event ..."); }} |
Обратите внимание на пример кода
Пример кода для этой статьи можно найти в репозитории spring-boot-thymeleaf . По умолчанию безопасность отключена в обоих профилях. Включите его, изменив свойство security.basic.enabled в application.properties .
| Ссылка: | Весенняя загрузка и события безопасности с Actuator от нашего партнера JCG Рафаля Боровца в блоге Codeleak.pl . |