servlet-authentication-events.md 4.9 KB
Newer Older
茶陵後's avatar
茶陵後 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
# Authentication Events

For each authentication that succeeds or fails, a `AuthenticationSuccessEvent` or `AbstractAuthenticationFailureEvent` is fired, respectively.

To listen for these events, you must first publish an `AuthenticationEventPublisher`.
Spring Security’s `DefaultAuthenticationEventPublisher` will probably do fine:

Java

```
@Bean
public AuthenticationEventPublisher authenticationEventPublisher
        (ApplicationEventPublisher applicationEventPublisher) {
    return new DefaultAuthenticationEventPublisher(applicationEventPublisher);
}
```

Kotlin

```
@Bean
fun authenticationEventPublisher
        (applicationEventPublisher: ApplicationEventPublisher?): AuthenticationEventPublisher {
    return DefaultAuthenticationEventPublisher(applicationEventPublisher)
}
```

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

Java

```
@Component
public class AuthenticationEvents {
	@EventListener
    public void onSuccess(AuthenticationSuccessEvent success) {
		// ...
    }

    @EventListener
    public void onFailure(AbstractAuthenticationFailureEvent failures) {
		// ...
    }
}
```

Kotlin

```
@Component
class AuthenticationEvents {
    @EventListener
    fun onSuccess(success: AuthenticationSuccessEvent?) {
        // ...
    }

    @EventListener
    fun onFailure(failures: AbstractAuthenticationFailureEvent?) {
        // ...
    }
}
```

While similar to `AuthenticationSuccessHandler` and `AuthenticationFailureHandler`, these are nice in that they can be used independently from the servlet API.

## Adding Exception Mappings

`DefaultAuthenticationEventPublisher` by default will publish an `AbstractAuthenticationFailureEvent` for the following events:

|           Exception            |                    Event                     |
|--------------------------------|----------------------------------------------|
|   `BadCredentialsException`    |  `AuthenticationFailureBadCredentialsEvent`  |
|  `UsernameNotFoundException`   |  `AuthenticationFailureBadCredentialsEvent`  |
|   `AccountExpiredException`    |     `AuthenticationFailureExpiredEvent`      |
|  `ProviderNotFoundException`   | `AuthenticationFailureProviderNotFoundEvent` |
|      `DisabledException`       |     `AuthenticationFailureDisabledEvent`     |
|       `LockedException`        |      `AuthenticationFailureLockedEvent`      |
|`AuthenticationServiceException`| `AuthenticationFailureServiceExceptionEvent` |
| `CredentialsExpiredException`  |`AuthenticationFailureCredentialsExpiredEvent`|
| `InvalidBearerTokenException`  |  `AuthenticationFailureBadCredentialsEvent`  |

The publisher does an exact `Exception` match, which means that sub-classes of these exceptions won’t also produce events.

To that end, you may want to supply additional mappings to the publisher via the `setAdditionalExceptionMappings` method:

Java

```
@Bean
public AuthenticationEventPublisher authenticationEventPublisher
        (ApplicationEventPublisher applicationEventPublisher) {
    Map<Class<? extends AuthenticationException>,
        Class<? extends AbstractAuthenticationFailureEvent>> mapping =
            Collections.singletonMap(FooException.class, FooEvent.class);
    AuthenticationEventPublisher authenticationEventPublisher =
        new DefaultAuthenticationEventPublisher(applicationEventPublisher);
    authenticationEventPublisher.setAdditionalExceptionMappings(mapping);
    return authenticationEventPublisher;
}
```

Kotlin

```
@Bean
fun authenticationEventPublisher
        (applicationEventPublisher: ApplicationEventPublisher?): AuthenticationEventPublisher {
    val mapping: Map<Class<out AuthenticationException>, Class<out AbstractAuthenticationFailureEvent>> =
            mapOf(Pair(FooException::class.java, FooEvent::class.java))
    val authenticationEventPublisher = DefaultAuthenticationEventPublisher(applicationEventPublisher)
    authenticationEventPublisher.setAdditionalExceptionMappings(mapping)
    return authenticationEventPublisher
}
```

## Default Event

And, you can supply a catch-all event to fire in the case of any `AuthenticationException`:

Java

```
@Bean
public AuthenticationEventPublisher authenticationEventPublisher
        (ApplicationEventPublisher applicationEventPublisher) {
    AuthenticationEventPublisher authenticationEventPublisher =
        new DefaultAuthenticationEventPublisher(applicationEventPublisher);
    authenticationEventPublisher.setDefaultAuthenticationFailureEvent
        (GenericAuthenticationFailureEvent.class);
    return authenticationEventPublisher;
}
```

Kotlin

```
@Bean
fun authenticationEventPublisher
        (applicationEventPublisher: ApplicationEventPublisher?): AuthenticationEventPublisher {
    val authenticationEventPublisher = DefaultAuthenticationEventPublisher(applicationEventPublisher)
    authenticationEventPublisher.setDefaultAuthenticationFailureEvent(GenericAuthenticationFailureEvent::class.java)
    return authenticationEventPublisher
}
```

[Logout](logout.html)[Authorization](../authorization/index.html)