6 Events - Reference Documentation
Authors: Burt Beckwith, Beverley Talbott
Version: 2.0.0
Table of Contents
6 Events
Spring Security fires application events after various security-related actions such as successful login, unsuccessful login, and so on. Spring Security uses two main event classes, AbstractAuthenticationEvent and AbstractAuthorizationEvent.6.1 Event Notification
You can set up event notifications in two ways. The sections that follow describe each approach in more detail.- Register an event listener, ignoring events that do not interest you. Spring allows only partial event subscription; you use generics to register the class of events that interest you, and you are notified of that class and all subclasses.
- Register one or more callback closures in
grails-app/conf/Config.groovy
that take advantage of the plugin'sgrails.plugin.springsecurity. SecurityEventListener
. The listener does the filtering for you.
AuthenticationEventPublisher
Spring Security publishes events using an AuthenticationEventPublisher which in turn fire events using the ApplicationEventPublisher. By default no events are fired since theAuthenticationEventPublisher
instance registered is a grails.plugin.springsecurity.authentication. NullAuthenticationEventPublisher
. But you can enable event publishing by setting grails.plugin.springsecurity.useSecurityEventListener = true
in grails-app/conf/Config.groovy
.You can use the useSecurityEventListener
setting to temporarily disable and enable the callbacks, or enable them per-environment.UsernameNotFoundException
Most authentication exceptions trigger an event with a similar name as described in this table:Exception | Event |
---|---|
AccountExpiredException | AuthenticationFailureExpiredEvent |
AuthenticationServiceException | AuthenticationFailureServiceExceptionEvent |
LockedException | AuthenticationFailureLockedEvent |
CredentialsExpiredException | AuthenticationFailureCredentialsExpiredEvent |
DisabledException | AuthenticationFailureDisabledEvent |
BadCredentialsException | AuthenticationFailureBadCredentialsEvent |
UsernameNotFoundException | AuthenticationFailureBadCredentialsEvent |
ProviderNotFoundException | AuthenticationFailureProviderNotFoundEvent |
UsernameNotFoundException
which triggers an AuthenticationFailureBadCredentialsEvent
just like a BadCredentialsException
. This is a good idea since it doesn't expose extra information - there's no differentiation between a bad password and a missing user. In addition, by default a missing user will trigger a BadCredentialsException
for the same reasons. You can configure Spring Security to re-throw the original UsernameNotFoundException
instead of converting it to a BadCredentialsException
by setting grails.plugin.springsecurity.dao. hideUserNotFoundExceptions = false
in grails-app/conf/Config.groovy
.Fortunately all subclasses of AbstractAuthenticationFailureEvent have a getException()
method that gives you access to the exception that triggered the event, so you can use that to differentiate between a bad password and a missing user (if hideUserNotFoundExceptions=false
).
6.2 Registering an Event Listener
Enable events withgrails.plugin.springsecurity.useSecurityEventListener = true
and create one or more Groovy or Java classes, for example:package com.foo.barimport org.springframework.context.ApplicationListener import org.springframework.security.authentication.event. AuthenticationSuccessEventclass MySecurityEventListener implements ApplicationListener<AuthenticationSuccessEvent> { void onApplicationEvent(AuthenticationSuccessEvent event) { // handle the event } }
grails-app/conf/spring/resources.groovy
:import com.foo.bar.MySecurityEventListenerbeans = {
mySecurityEventListener(MySecurityEventListener)
}
6.3 Registering Callback Closures
Alternatively, enable events withgrails.plugin.springsecurity.useSecurityEventListener = true
and register one or more callback closure(s) in grails-app/conf/Config.groovy
and let SecurityEventListener
do the filtering.Implement the event handlers that you need, for example:grails {
plugin {
springsecurity {
useSecurityEventListener = true onInteractiveAuthenticationSuccessEvent = { e, appCtx ->
// handle InteractiveAuthenticationSuccessEvent
} onAbstractAuthenticationFailureEvent = { e, appCtx ->
// handle AbstractAuthenticationFailureEvent
} onAuthenticationSuccessEvent = { e, appCtx ->
// handle AuthenticationSuccessEvent
} onAuthenticationSwitchUserEvent = { e, appCtx ->
// handle AuthenticationSwitchUserEvent
} onAuthorizationEvent = { e, appCtx ->
// handle AuthorizationEvent
}
}
}
}
AuthenticationSuccessEvent
. This event fires before the Authentication
is registered in the SecurityContextHolder
, which means that the springSecurityService
methods that access the logged-in user will not work. Later in the processing a second event is fired, an InteractiveAuthenticationSuccessEvent
, and when this happens the SecurityContextHolder
will have the Authentication
. Depending on your needs, you can implement a callback for either or both events.