В SpringFramework есть интерфейс org.springframework.context.ApplicationListener . С помощью реализаций этого интерфейса можно обрабатывать различные события приложения. Для этого нужно зарегистрировать бин с классом, реализующим этот интерфейс ApplicationListener, и Spring Framework будет сам вызывать его при возникновении событий. Для регистрации бина можно использовать любой способ: в XML-файле через тег <bean>, через аннотацию @Component и сканирование компонентов, через Java-конфигурацию. Интересующее событие указывается в generic-параметре.
Например, можно обрабатывать успешный вход и выход пользователей в Spring Security. Для этого используются события org.springframework.security.authentication.event.AuthenticationSuccessEvent и org.springframework.security.core.session.SessionDestroyedEvent.
Пример обработчика события успешного входа пользователя в систему:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import org.springframework.context.ApplicationListener; import org.springframework.security.authentication.event.AuthenticationSuccessEvent; import org.springframework.security.core.userdetails.UserDetails; public class AuthenticationSuccessListenerImpl implements ApplicationListener<AuthenticationSuccessEvent> { @Override public void onApplicationEvent(AuthenticationSuccessEvent appEvent) { AuthenticationSuccessEvent event = (AuthenticationSuccessEvent) appEvent; UserDetails userDetails = (UserDetails) event.getAuthentication().getPrincipal(); if (userDetails instanceof UserDetailsImpl) { // Обрабатываем успешный вход в систему (запись в лог или что там). // UserDetailsImpl - это ваша реализация интерфейса UserDetails // ... } } } |
Пример обработчика события завершения сессии пользователя (выхода пользователя):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import java.util.List; import org.springframework.context.ApplicationListener; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.session.SessionDestroyedEvent; import org.springframework.security.core.userdetails.UserDetails; public class LogoutListenerImpl implements ApplicationListener<SessionDestroyedEvent> { @Override public void onApplicationEvent(SessionDestroyedEvent event) { List<SecurityContext> lstSecurityContext = event.getSecurityContexts(); UserDetails userDetails; for (SecurityContext securityContext : lstSecurityContext) { userDetails = (UserDetails) securityContext.getAuthentication() .getPrincipal(); if (userDetails instanceof UserDetailsImpl) { // Обработка завершения сессии (запись в лог или что там) // UserDetailsImpl - ваша реализация UserDetails // ... } } } } |
Чтобы событие уничтожения сессии SessionDestroyedEvent работало, нужно также добавить в web.xml ещё один listener:
1 2 3 |
<listener> <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class> </listener> |
Вставьте его сразу после ContextLoaderListener.
При этом можно не только записывать в лог, но и выполнять любые другие необходимые действия: отправка почты, вычисление рабочего времени и т. д.
А есть в спринге уязвмости, подобные этой?
http://www.linux.org.ru/news/security/12200062
Вполне возможно.