mirror of
				https://github.com/spring-projects/spring-security.git
				synced 2025-11-04 08:39:05 +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
 | 
						|
    }
 | 
						|
}
 | 
						|
----
 | 
						|
======
 |