mirror of
				https://github.com/spring-projects/spring-security.git
				synced 2025-10-30 22:28:46 +00:00 
			
		
		
		
	Document Authorization Events
Issue gh-9288
This commit is contained in:
		
							parent
							
								
									bdd5f86526
								
							
						
					
					
						commit
						ce720ad38e
					
				| @ -54,6 +54,7 @@ | ||||
| *** xref:servlet/authorization/secure-objects.adoc[Secure Object Implementations] | ||||
| *** xref:servlet/authorization/method-security.adoc[Method Security] | ||||
| *** xref:servlet/authorization/acls.adoc[Domain Object Security ACLs] | ||||
| *** xref:servlet/authorization/events.adoc[Authorization Events] | ||||
| ** xref:servlet/oauth2/index.adoc[OAuth2] | ||||
| *** xref:servlet/oauth2/login/index.adoc[OAuth2 Log In] | ||||
| **** xref:servlet/oauth2/login/core.adoc[Core Configuration] | ||||
|  | ||||
							
								
								
									
										160
									
								
								docs/modules/ROOT/pages/servlet/authorization/events.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								docs/modules/ROOT/pages/servlet/authorization/events.adoc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,160 @@ | ||||
| [[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`: | ||||
| 
 | ||||
| ==== | ||||
| .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: | ||||
| 
 | ||||
| ==== | ||||
| .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: | ||||
| 
 | ||||
| ==== | ||||
| .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 | ||||
|     } | ||||
| } | ||||
| ---- | ||||
| ==== | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user