Переглянути джерело

Added methods to add filter relatively in ServerHttpSecurity

Addition of two new methods addFilterBefore and addFilterAfter in
ServerHttpSecurity to allow addition of WebFilter before and after of
specified order

Fixes: gh-6138
Ankur Pathak 6 роки тому
батько
коміт
8b3fb55aea

+ 26 - 0
config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java

@@ -288,6 +288,32 @@ public class ServerHttpSecurity {
 		return this;
 	}
 
+	/**
+	 * Adds a {@link WebFilter} before specific position.
+	 * @param webFilter the {@link WebFilter} to add
+	 * @param order the place before which to insert the {@link WebFilter}
+	 * @return the {@link ServerHttpSecurity} to continue configuring
+	 * @since 5.2.0
+	 * @author Ankur Pathak
+	 */
+	public ServerHttpSecurity addFilterBefore(WebFilter webFilter, SecurityWebFiltersOrder order) {
+		this.webFilters.add(new OrderedWebFilter(webFilter, order.getOrder() - 1));
+		return this;
+	}
+
+	/**
+	 * Adds a {@link WebFilter} after specific position.
+	 * @param webFilter the {@link WebFilter} to add
+	 * @param order the place after which to insert the {@link WebFilter}
+	 * @return the {@link ServerHttpSecurity} to continue configuring
+	 * @since 5.2.0
+	 * @author Ankur Pathak
+	 */
+	public ServerHttpSecurity addFilterAfter(WebFilter webFilter, SecurityWebFiltersOrder order) {
+		this.webFilters.add(new OrderedWebFilter(webFilter, order.getOrder() + 1));
+		return this;
+	}
+
 	/**
 	 * Gets the ServerExchangeMatcher that determines which requests apply to this HttpSecurity instance.
 	 * @return the ServerExchangeMatcher that determines which requests apply to this HttpSecurity instance.

+ 34 - 0
config/src/test/java/org/springframework/security/config/web/server/ServerHttpSecurityTests.java

@@ -34,6 +34,8 @@ import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
 
+import org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter;
+import org.springframework.web.server.WebFilterChain;
 import reactor.core.publisher.Mono;
 import reactor.test.publisher.TestPublisher;
 
@@ -190,6 +192,30 @@ public class ServerHttpSecurityTests {
 				.isEqualTo(Arrays.asList(SecurityContextServerLogoutHandler.class, CsrfServerLogoutHandler.class));
 	}
 
+	@Test
+	@SuppressWarnings("unchecked")
+	public void addFilterAfterIsApplied(){
+		SecurityWebFilterChain securityWebFilterChain =  this.http.addFilterAfter(new TestWebFilter(), SecurityWebFiltersOrder.SECURITY_CONTEXT_SERVER_WEB_EXCHANGE).build();
+		List filters = securityWebFilterChain.getWebFilters().map(WebFilter::getClass).collectList().block();
+
+		assertThat(filters).isNotNull()
+				.isNotEmpty()
+				.containsSequence(SecurityContextServerWebExchangeWebFilter.class, TestWebFilter.class);
+
+	}
+
+	@Test
+	@SuppressWarnings("unchecked")
+	public void addFilterBeforeIsApplied(){
+		SecurityWebFilterChain securityWebFilterChain =  this.http.addFilterBefore(new TestWebFilter(), SecurityWebFiltersOrder.SECURITY_CONTEXT_SERVER_WEB_EXCHANGE).build();
+		List filters = securityWebFilterChain.getWebFilters().map(WebFilter::getClass).collectList().block();
+
+		assertThat(filters).isNotNull()
+				.isNotEmpty()
+				.containsSequence(TestWebFilter.class, SecurityContextServerWebExchangeWebFilter.class);
+
+	}
+
 	private <T extends WebFilter> Optional<T> getWebFilter(SecurityWebFilterChain filterChain, Class<T> filterClass) {
 		return (Optional<T>) filterChain.getWebFilters()
 				.filter(Objects::nonNull)
@@ -214,4 +240,12 @@ public class ServerHttpSecurityTests {
 				.map(e -> e.getRequest().getPath().pathWithinApplication().value());
 		}
 	}
+
+	private static class TestWebFilter implements WebFilter {
+
+		@Override
+		public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
+			return chain.filter(exchange);
+		}
+	}
 }