浏览代码

Polish ExceptionTranslateWebFilter

- Isolated exception construction
- Isolated entry point subscription

Issue gh-16444
Josh Cummings 5 月之前
父节点
当前提交
464e506429

+ 19 - 13
web/src/main/java/org/springframework/security/web/server/authorization/ExceptionTranslationWebFilter.java

@@ -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");
  * you may not use this file except in compliance with the License.
@@ -50,14 +50,19 @@ public class ExceptionTranslationWebFilter implements WebFilter {
 	@Override
 	public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
 		return chain.filter(exchange)
-			.onErrorResume(AccessDeniedException.class, (denied) -> exchange.getPrincipal()
-				.filter((principal) -> (!(principal instanceof Authentication) || (principal instanceof Authentication
-						&& (this.authenticationTrustResolver.isAuthenticated((Authentication) principal)))))
-				.switchIfEmpty(commenceAuthentication(exchange,
-						new InsufficientAuthenticationException(
-								"Full authentication is required to access this resource")))
-				.flatMap((principal) -> this.accessDeniedHandler.handle(exchange, denied))
-				.then());
+			.onErrorResume(AccessDeniedException.class,
+					(denied) -> exchange.getPrincipal()
+						.switchIfEmpty(Mono.defer(() -> commenceAuthentication(exchange, null)))
+						.flatMap((principal) -> {
+							if (!(principal instanceof Authentication authentication)) {
+								return this.accessDeniedHandler.handle(exchange, denied);
+							}
+							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;
 	}
 
-	private <T> Mono<T> commenceAuthentication(ServerWebExchange exchange, AuthenticationException denied) {
-		return this.authenticationEntryPoint
-			.commence(exchange, new AuthenticationCredentialsNotFoundException("Not Authenticated", denied))
-			.then(Mono.empty());
+	private <T> Mono<T> commenceAuthentication(ServerWebExchange exchange, Authentication authentication) {
+		AuthenticationException cause = new InsufficientAuthenticationException(
+				"Full authentication is required to access this resource");
+		AuthenticationException ex = new AuthenticationCredentialsNotFoundException("Not Authenticated", cause);
+		return this.authenticationEntryPoint.commence(exchange, ex).then(Mono.empty());
 	}
 
 }

+ 1 - 2
web/src/test/java/org/springframework/security/web/server/authorization/ExceptionTranslationWebFilterTests.java

@@ -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");
  * you may not use this file except in compliance with the License.
@@ -129,7 +129,6 @@ public class ExceptionTranslationWebFilterTests {
 	@Test
 	public void filterWhenAccessDeniedExceptionAndAuthenticatedThenHandled() {
 		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.chain.filter(this.exchange)).willReturn(Mono.error(new AccessDeniedException("Not Authorized")));
 		StepVerifier.create(this.filter.filter(this.exchange, this.chain)).expectComplete().verify();