123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- [[servlet-events]]
- = Authorization Events
- For each authorization that is denied, an `AuthorizationDeniedEvent` is fired.
- Also, it's possible to fire and `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 create your own event publisher that filters success events.
- For example, the following publisher only publishes authorization grants where `ROLE_ADMIN` was required:
- [tabs]
- ======
- Java::
- +
- [source,java,role="primary"]
- ----
- @Component
- public class MyAuthorizationEventPublisher implements AuthorizationEventPublisher {
- private final ApplicationEventPublisher publisher;
- private final AuthorizationEventPublisher delegate;
- public MyAuthorizationEventPublisher(ApplicationEventPublisher publisher) {
- this.publisher = publisher;
- this.delegate = new SpringAuthorizationEventPublisher(publisher);
- }
- @Override
- public <T> void publishAuthorizationEvent(Supplier<Authentication> authentication,
- T object, AuthorizationDecision decision) {
- if (decision == null) {
- return;
- }
- if (!decision.isGranted()) {
- this.delegate.publishAuthorizationEvent(authentication, object, decision);
- return;
- }
- if (shouldThisEventBePublished(decision)) {
- AuthorizationGrantedEvent granted = new AuthorizationGrantedEvent(
- authentication, object, decision);
- this.publisher.publishEvent(granted);
- }
- }
- private boolean shouldThisEventBePublished(AuthorizationDecision decision) {
- if (!(decision instanceof AuthorityAuthorizationDecision)) {
- return false;
- }
- Collection<GrantedAuthority> authorities = ((AuthorityAuthorizationDecision) decision).getAuthorities();
- for (GrantedAuthority authority : authorities) {
- if ("ROLE_ADMIN".equals(authority.getAuthority())) {
- return true;
- }
- }
- return false;
- }
- }
- ----
- Kotlin::
- +
- [source,kotlin,role="secondary"]
- ----
- @Component
- class MyAuthorizationEventPublisher(val publisher: ApplicationEventPublisher,
- val delegate: SpringAuthorizationEventPublisher = SpringAuthorizationEventPublisher(publisher)):
- AuthorizationEventPublisher {
- override fun <T : Any?> publishAuthorizationEvent(
- authentication: Supplier<Authentication>?,
- `object`: T,
- decision: AuthorizationDecision?
- ) {
- if (decision == null) {
- return
- }
- if (!decision.isGranted) {
- this.delegate.publishAuthorizationEvent(authentication, `object`, decision)
- return
- }
- if (shouldThisEventBePublished(decision)) {
- val granted = AuthorizationGrantedEvent(authentication, `object`, decision)
- this.publisher.publishEvent(granted)
- }
- }
- private fun shouldThisEventBePublished(decision: AuthorizationDecision): Boolean {
- if (decision !is AuthorityAuthorizationDecision) {
- return false
- }
- val authorities = decision.authorities
- for (authority in authorities) {
- if ("ROLE_ADMIN" == authority.authority) {
- return true
- }
- }
- return false
- }
- }
- ----
- ======
|