mirror of
				https://github.com/spring-projects/spring-security.git
				synced 2025-10-28 21:28:44 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			170 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| [[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
 | |
|     }
 | |
| }
 | |
| ----
 | |
| ======
 |