You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
3.2 KiB
123 lines
3.2 KiB
[[servlet-events]] |
|
= Authorization Events |
|
|
|
For each authorization that is denied, an `AuthorizationDeniedEvent` is fired. |
|
Also, it's possible to fire an `AuthorizationGrantedEvent` for authorizations that are granted. |
|
|
|
To listen for these events, you must first publish an `AuthorizationEventPublisher`. |
|
|
|
Spring Security's `SpringAuthorizationEventPublisher` will probably do fine. |
|
It comes publishes authorization events using Spring's `ApplicationEventPublisher`: |
|
|
|
[tabs] |
|
====== |
|
Java:: |
|
+ |
|
[source,java,role="primary"] |
|
---- |
|
@Bean |
|
public AuthorizationEventPublisher authorizationEventPublisher |
|
(ApplicationEventPublisher applicationEventPublisher) { |
|
return new SpringAuthorizationEventPublisher(applicationEventPublisher); |
|
} |
|
---- |
|
|
|
Kotlin:: |
|
+ |
|
[source,kotlin,role="secondary"] |
|
---- |
|
@Bean |
|
fun authorizationEventPublisher |
|
(applicationEventPublisher: ApplicationEventPublisher?): AuthorizationEventPublisher { |
|
return SpringAuthorizationEventPublisher(applicationEventPublisher) |
|
} |
|
---- |
|
====== |
|
|
|
Then, you can use Spring's `@EventListener` support: |
|
|
|
[tabs] |
|
====== |
|
Java:: |
|
+ |
|
[source,java,role="primary"] |
|
---- |
|
@Component |
|
public class AuthenticationEvents { |
|
|
|
@EventListener |
|
public void onFailure(AuthorizationDeniedEvent failure) { |
|
// ... |
|
} |
|
} |
|
---- |
|
|
|
Kotlin:: |
|
+ |
|
[source,kotlin,role="secondary"] |
|
---- |
|
@Component |
|
class AuthenticationEvents { |
|
|
|
@EventListener |
|
fun onFailure(failure: AuthorizationDeniedEvent?) { |
|
// ... |
|
} |
|
} |
|
---- |
|
====== |
|
|
|
[[authorization-granted-events]] |
|
== Authorization Granted Events |
|
|
|
Because ``AuthorizationGrantedEvent``s have the potential to be quite noisy, they are not published by default. |
|
|
|
In fact, publishing these events will likely require some business logic on your part to ensure that your application is not inundated with noisy authorization events. |
|
|
|
You can provide your own predicate that filters success events. |
|
For example, the following publisher only publishes authorization grants where `ROLE_ADMIN` was required: |
|
|
|
[tabs] |
|
====== |
|
Java:: |
|
+ |
|
[source,java,role="primary"] |
|
---- |
|
@Bean |
|
AuthorizationEventPublisher authorizationEventPublisher() { |
|
SpringAuthorizationEventPublisher eventPublisher = new SpringAuthorizationEventPublisher(); |
|
eventPublisher.setShouldPublishEvent((result) -> { |
|
if (!result.isGranted()) { |
|
return true; |
|
} |
|
if (result instanceof AuthorityAuthorizationDecision decision) { |
|
Collection<GrantedAuthority> authorities = decision.getAuthorities(); |
|
return AuthorityUtils.authorityListToSet(authorities).contains("ROLE_ADMIN"); |
|
} |
|
return false; |
|
}); |
|
return eventPublisher; |
|
} |
|
---- |
|
|
|
Kotlin:: |
|
+ |
|
[source,kotlin,role="secondary"] |
|
---- |
|
@Bean |
|
fun authorizationEventPublisher(): AuthorizationEventPublisher { |
|
val eventPublisher = SpringAuthorizationEventPublisher() |
|
eventPublisher.setShouldPublishEvent { (result) -> |
|
if (!result.isGranted()) { |
|
return true |
|
} |
|
if (decision is AuthorityAuthorizationDecision) { |
|
val authorities = decision.getAuthorities() |
|
return AuthorityUtils.authorityListToSet(authorities).contains("ROLE_ADMIN") |
|
} |
|
return false |
|
} |
|
return eventPublisher |
|
} |
|
---- |
|
======
|
|
|