Polish ExceptionTranslateWebFilter

- Isolated exception construction
- Isolated entry point subscription

Issue gh-16444
This commit is contained in:
Josh Cummings 2025-03-21 17:43:39 -06:00
parent 60bed7f68a
commit 464e506429
2 changed files with 20 additions and 15 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2022 the original author or authors. * Copyright 2002-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -50,14 +50,19 @@ public class ExceptionTranslationWebFilter implements WebFilter {
@Override @Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return chain.filter(exchange) return chain.filter(exchange)
.onErrorResume(AccessDeniedException.class, (denied) -> exchange.getPrincipal() .onErrorResume(AccessDeniedException.class,
.filter((principal) -> (!(principal instanceof Authentication) || (principal instanceof Authentication (denied) -> exchange.getPrincipal()
&& (this.authenticationTrustResolver.isAuthenticated((Authentication) principal))))) .switchIfEmpty(Mono.defer(() -> commenceAuthentication(exchange, null)))
.switchIfEmpty(commenceAuthentication(exchange, .flatMap((principal) -> {
new InsufficientAuthenticationException( if (!(principal instanceof Authentication authentication)) {
"Full authentication is required to access this resource"))) return this.accessDeniedHandler.handle(exchange, denied);
.flatMap((principal) -> this.accessDeniedHandler.handle(exchange, denied)) }
.then()); if (this.authenticationTrustResolver.isAuthenticated(authentication)) {
return this.accessDeniedHandler.handle(exchange, denied);
}
return commenceAuthentication(exchange, authentication);
})
.then());
} }
/** /**
@ -92,10 +97,11 @@ public class ExceptionTranslationWebFilter implements WebFilter {
this.authenticationTrustResolver = authenticationTrustResolver; this.authenticationTrustResolver = authenticationTrustResolver;
} }
private <T> Mono<T> commenceAuthentication(ServerWebExchange exchange, AuthenticationException denied) { private <T> Mono<T> commenceAuthentication(ServerWebExchange exchange, Authentication authentication) {
return this.authenticationEntryPoint AuthenticationException cause = new InsufficientAuthenticationException(
.commence(exchange, new AuthenticationCredentialsNotFoundException("Not Authenticated", denied)) "Full authentication is required to access this resource");
.then(Mono.empty()); AuthenticationException ex = new AuthenticationCredentialsNotFoundException("Not Authenticated", cause);
return this.authenticationEntryPoint.commence(exchange, ex).then(Mono.empty());
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2022 the original author or authors. * Copyright 2002-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -129,7 +129,6 @@ public class ExceptionTranslationWebFilterTests {
@Test @Test
public void filterWhenAccessDeniedExceptionAndAuthenticatedThenHandled() { public void filterWhenAccessDeniedExceptionAndAuthenticatedThenHandled() {
given(this.deniedHandler.handle(any(), any())).willReturn(this.deniedPublisher.mono()); given(this.deniedHandler.handle(any(), any())).willReturn(this.deniedPublisher.mono());
given(this.entryPoint.commence(any(), any())).willReturn(this.entryPointPublisher.mono());
given(this.exchange.getPrincipal()).willReturn(Mono.just(this.principal)); given(this.exchange.getPrincipal()).willReturn(Mono.just(this.principal));
given(this.chain.filter(this.exchange)).willReturn(Mono.error(new AccessDeniedException("Not Authorized"))); given(this.chain.filter(this.exchange)).willReturn(Mono.error(new AccessDeniedException("Not Authorized")));
StepVerifier.create(this.filter.filter(this.exchange, this.chain)).expectComplete().verify(); StepVerifier.create(this.filter.filter(this.exchange, this.chain)).expectComplete().verify();