events.adoc 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. [[servlet-events]]
  2. = Authorization Events
  3. For each authorization that is denied, an `AuthorizationDeniedEvent` is fired.
  4. Also, it's possible to fire an `AuthorizationGrantedEvent` for authorizations that are granted.
  5. To listen for these events, you must first publish an `AuthorizationEventPublisher`.
  6. Spring Security's `SpringAuthorizationEventPublisher` will probably do fine.
  7. It comes publishes authorization events using Spring's `ApplicationEventPublisher`:
  8. [tabs]
  9. ======
  10. Java::
  11. +
  12. [source,java,role="primary"]
  13. ----
  14. @Bean
  15. public AuthorizationEventPublisher authorizationEventPublisher
  16. (ApplicationEventPublisher applicationEventPublisher) {
  17. return new SpringAuthorizationEventPublisher(applicationEventPublisher);
  18. }
  19. ----
  20. Kotlin::
  21. +
  22. [source,kotlin,role="secondary"]
  23. ----
  24. @Bean
  25. fun authorizationEventPublisher
  26. (applicationEventPublisher: ApplicationEventPublisher?): AuthorizationEventPublisher {
  27. return SpringAuthorizationEventPublisher(applicationEventPublisher)
  28. }
  29. ----
  30. ======
  31. Then, you can use Spring's `@EventListener` support:
  32. [tabs]
  33. ======
  34. Java::
  35. +
  36. [source,java,role="primary"]
  37. ----
  38. @Component
  39. public class AuthenticationEvents {
  40. @EventListener
  41. public void onFailure(AuthorizationDeniedEvent failure) {
  42. // ...
  43. }
  44. }
  45. ----
  46. Kotlin::
  47. +
  48. [source,kotlin,role="secondary"]
  49. ----
  50. @Component
  51. class AuthenticationEvents {
  52. @EventListener
  53. fun onFailure(failure: AuthorizationDeniedEvent?) {
  54. // ...
  55. }
  56. }
  57. ----
  58. ======
  59. [[authorization-granted-events]]
  60. == Authorization Granted Events
  61. Because ``AuthorizationGrantedEvent``s have the potential to be quite noisy, they are not published by default.
  62. 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.
  63. You can create your own event publisher that filters success events.
  64. For example, the following publisher only publishes authorization grants where `ROLE_ADMIN` was required:
  65. [tabs]
  66. ======
  67. Java::
  68. +
  69. [source,java,role="primary"]
  70. ----
  71. @Component
  72. public class MyAuthorizationEventPublisher implements AuthorizationEventPublisher {
  73. private final ApplicationEventPublisher publisher;
  74. private final AuthorizationEventPublisher delegate;
  75. public MyAuthorizationEventPublisher(ApplicationEventPublisher publisher) {
  76. this.publisher = publisher;
  77. this.delegate = new SpringAuthorizationEventPublisher(publisher);
  78. }
  79. @Override
  80. public <T> void publishAuthorizationEvent(Supplier<Authentication> authentication,
  81. T object, AuthorizationResult result) {
  82. if (result == null) {
  83. return;
  84. }
  85. if (!result.isGranted()) {
  86. this.delegate.publishAuthorizationEvent(authentication, object, result);
  87. return;
  88. }
  89. if (shouldThisEventBePublished(result)) {
  90. AuthorizationGrantedEvent granted = new AuthorizationGrantedEvent(
  91. authentication, object, result);
  92. this.publisher.publishEvent(granted);
  93. }
  94. }
  95. private boolean shouldThisEventBePublished(AuthorizationResult result) {
  96. if (result instanceof AuthorityAuthorizationDecision authorityAuthorizationDecision) {
  97. Collection<GrantedAuthority> authorities = authorityAuthorizationDecision.getAuthorities();
  98. for (GrantedAuthority authority : authorities) {
  99. if ("ROLE_ADMIN".equals(authority.getAuthority())) {
  100. return true;
  101. }
  102. }
  103. }
  104. return false;
  105. }
  106. }
  107. ----
  108. Kotlin::
  109. +
  110. [source,kotlin,role="secondary"]
  111. ----
  112. @Component
  113. class MyAuthorizationEventPublisher(val publisher: ApplicationEventPublisher,
  114. val delegate: SpringAuthorizationEventPublisher = SpringAuthorizationEventPublisher(publisher)):
  115. AuthorizationEventPublisher {
  116. override fun <T : Any?> publishAuthorizationEvent(
  117. authentication: Supplier<Authentication>?,
  118. `object`: T,
  119. result: AuthorizationResult?
  120. ) {
  121. if (result == null) {
  122. return
  123. }
  124. if (!result.isGranted) {
  125. this.delegate.publishAuthorizationEvent(authentication, `object`, result)
  126. return
  127. }
  128. if (shouldThisEventBePublished(result)) {
  129. val granted = AuthorizationGrantedEvent(authentication, `object`, result)
  130. this.publisher.publishEvent(granted)
  131. }
  132. }
  133. private fun shouldThisEventBePublished(result: AuthorizationResult): Boolean {
  134. if (decision !is AuthorityAuthorizationDecision) {
  135. return false
  136. }
  137. val authorities = decision.authorities
  138. for (authority in authorities) {
  139. if ("ROLE_ADMIN" == authority.authority) {
  140. return true
  141. }
  142. }
  143. return false
  144. }
  145. }
  146. ----
  147. ======