Authorization Events

对于每次被拒绝的授权,都会触发 AuthorizationDeniedEvent。此外,还可以为已授予的授权触发 AuthorizationGrantedEvent

For each authorization that is denied, an AuthorizationDeniedEvent is fired. Also, it’s possible to fire an AuthorizationGrantedEvent for authorizations that are granted.

要监听这些事件,您必须首先发布 AuthorizationEventPublisher

To listen for these events, you must first publish an AuthorizationEventPublisher.

Spring Security 的 SpringAuthorizationEventPublisher 可能很好用。它使用 Spring 的 ApplicationEventPublisher 发布授权事件:

Spring Security’s SpringAuthorizationEventPublisher will probably do fine. It comes publishes authorization events using Spring’s ApplicationEventPublisher:

  • Java

  • Kotlin

@Bean
public AuthorizationEventPublisher authorizationEventPublisher
        (ApplicationEventPublisher applicationEventPublisher) {
    return new SpringAuthorizationEventPublisher(applicationEventPublisher);
}
@Bean
fun authorizationEventPublisher
        (applicationEventPublisher: ApplicationEventPublisher?): AuthorizationEventPublisher {
    return SpringAuthorizationEventPublisher(applicationEventPublisher)
}

然后,您可以使用 Spring 的 @EventListener 支持:

Then, you can use Spring’s @EventListener support:

  • Java

  • Kotlin

@Component
public class AuthenticationEvents {

    @EventListener
    public void onFailure(AuthorizationDeniedEvent failure) {
		// ...
    }
}
@Component
class AuthenticationEvents {

    @EventListener
    fun onFailure(failure: AuthorizationDeniedEvent?) {
        // ...
    }
}

Authorization Granted Events

因为 AuthorizationGrantedEvent 可能相当吵闹,所以它们不会默认发布。

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.

您可以创建筛选成功事件的事件发布器。例如,以下发布只会发布需要” ROLE_ADMIN” 的授权授予:

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

  • Kotlin

@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;
    }
}
@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
    }
}