events.adoc 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. [[servlet-events]]
  2. == Authentication Events
  3. For each authentication that succeeds or fails, a `AuthenticationSuccessEvent` or `AbstractAuthenticationFailureEvent` is fired, respectively.
  4. To listen for these events, you must first publish an `AuthenticationEventPublisher`.
  5. Spring Security's `DefaultAuthenticationEventPublisher` will probably do fine:
  6. ====
  7. .Java
  8. [source,java,role="primary"]
  9. ----
  10. @Bean
  11. public AuthenticationEventPublisher authenticationEventPublisher
  12. (ApplicationEventPublisher applicationEventPublisher) {
  13. return new DefaultAuthenticationEventPublisher(applicationEventPublisher);
  14. }
  15. ----
  16. .Kotlin
  17. [source,kotlin,role="secondary"]
  18. ----
  19. @Bean
  20. fun authenticationEventPublisher
  21. (applicationEventPublisher: ApplicationEventPublisher?): AuthenticationEventPublisher {
  22. return DefaultAuthenticationEventPublisher(applicationEventPublisher)
  23. }
  24. ----
  25. ====
  26. Then, you can use Spring's `@EventListener` support:
  27. ====
  28. .Java
  29. [source,java,role="primary"]
  30. ----
  31. @Component
  32. public class AuthenticationEvents {
  33. @EventListener
  34. public void onSuccess(AuthenticationSuccessEvent success) {
  35. // ...
  36. }
  37. @EventListener
  38. public void onFailure(AbstractAuthenticationFailureEvent failures) {
  39. // ...
  40. }
  41. }
  42. ----
  43. .Kotlin
  44. [source,kotlin,role="secondary"]
  45. ----
  46. @Component
  47. class AuthenticationEvents {
  48. @EventListener
  49. fun onSuccess(success: AuthenticationSuccessEvent?) {
  50. // ...
  51. }
  52. @EventListener
  53. fun onFailure(failures: AbstractAuthenticationFailureEvent?) {
  54. // ...
  55. }
  56. }
  57. ----
  58. ====
  59. While similar to `AuthenticationSuccessHandler` and `AuthenticationFailureHandler`, these are nice in that they can be used independently from the servlet API.
  60. === Adding Exception Mappings
  61. `DefaultAuthenticationEventPublisher` by default will publish an `AbstractAuthenticationFailureEvent` for the following events:
  62. |============
  63. | Exception | Event
  64. | `BadCredentialsException` | `AuthenticationFailureBadCredentialsEvent`
  65. | `UsernameNotFoundException` | `AuthenticationFailureBadCredentialsEvent`
  66. | `AccountExpiredException` | `AuthenticationFailureExpiredEvent`
  67. | `ProviderNotFoundException` | `AuthenticationFailureProviderNotFoundEvent`
  68. | `DisabledException` | `AuthenticationFailureDisabledEvent`
  69. | `LockedException` | `AuthenticationFailureLockedEvent`
  70. | `AuthenticationServiceException` | `AuthenticationFailureServiceExceptionEvent`
  71. | `CredentialsExpiredException` | `AuthenticationFailureCredentialsExpiredEvent`
  72. | `InvalidBearerTokenException` | `AuthenticationFailureBadCredentialsEvent`
  73. |============
  74. The publisher does an exact `Exception` match, which means that sub-classes of these exceptions won't also produce events.
  75. To that end, you may want to supply additional mappings to the publisher via the `setAdditionalExceptionMappings` method:
  76. ====
  77. .Java
  78. [source,java,role="primary"]
  79. ----
  80. @Bean
  81. public AuthenticationEventPublisher authenticationEventPublisher
  82. (ApplicationEventPublisher applicationEventPublisher) {
  83. Map<Class<? extends AuthenticationException>,
  84. Class<? extends AbstractAuthenticationFailureEvent>> mapping =
  85. Collections.singletonMap(FooException.class, FooEvent.class);
  86. AuthenticationEventPublisher authenticationEventPublisher =
  87. new DefaultAuthenticationEventPublisher(applicationEventPublisher);
  88. authenticationEventPublisher.setAdditionalExceptionMappings(mapping);
  89. return authenticationEventPublisher;
  90. }
  91. ----
  92. .Kotlin
  93. [source,kotlin,role="secondary"]
  94. ----
  95. @Bean
  96. fun authenticationEventPublisher
  97. (applicationEventPublisher: ApplicationEventPublisher?): AuthenticationEventPublisher {
  98. val mapping: Map<Class<out AuthenticationException>, Class<out AbstractAuthenticationFailureEvent>> =
  99. mapOf(Pair(FooException::class.java, FooEvent::class.java))
  100. val authenticationEventPublisher = DefaultAuthenticationEventPublisher(applicationEventPublisher)
  101. authenticationEventPublisher.setAdditionalExceptionMappings(mapping)
  102. return authenticationEventPublisher
  103. }
  104. ----
  105. ====
  106. === Default Event
  107. And, you can supply a catch-all event to fire in the case of any `AuthenticationException`:
  108. ====
  109. .Java
  110. [source,java,role="primary"]
  111. ----
  112. @Bean
  113. public AuthenticationEventPublisher authenticationEventPublisher
  114. (ApplicationEventPublisher applicationEventPublisher) {
  115. AuthenticationEventPublisher authenticationEventPublisher =
  116. new DefaultAuthenticationEventPublisher(applicationEventPublisher);
  117. authenticationEventPublisher.setDefaultAuthenticationFailureEvent
  118. (GenericAuthenticationFailureEvent.class);
  119. return authenticationEventPublisher;
  120. }
  121. ----
  122. .Kotlin
  123. [source,kotlin,role="secondary"]
  124. ----
  125. @Bean
  126. fun authenticationEventPublisher
  127. (applicationEventPublisher: ApplicationEventPublisher?): AuthenticationEventPublisher {
  128. val authenticationEventPublisher = DefaultAuthenticationEventPublisher(applicationEventPublisher)
  129. authenticationEventPublisher.setDefaultAuthenticationFailureEvent(GenericAuthenticationFailureEvent::class.java)
  130. return authenticationEventPublisher
  131. }
  132. ----
  133. ====