Bladeren bron

Merge branch '6.3.x'

Josh Cummings 1 jaar geleden
bovenliggende
commit
81abc453fe

+ 14 - 39
config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2023 the original author or authors.
+ * Copyright 2002-2024 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.
@@ -22,6 +22,7 @@ import java.util.Collection;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Function;
 
@@ -203,36 +204,15 @@ public abstract class AbstractRequestMatcherRegistry<C> {
 		if (servletContext == null) {
 			return requestMatchers(RequestMatchers.antMatchersAsArray(method, patterns));
 		}
-		boolean isProgrammaticApiAvailable = isProgrammaticApiAvailable(servletContext);
 		List<RequestMatcher> matchers = new ArrayList<>();
 		for (String pattern : patterns) {
 			AntPathRequestMatcher ant = new AntPathRequestMatcher(pattern, (method != null) ? method.name() : null);
 			MvcRequestMatcher mvc = createMvcMatchers(method, pattern).get(0);
-			if (isProgrammaticApiAvailable) {
-				matchers.add(resolve(ant, mvc, servletContext));
-			}
-			else {
-				this.logger
-					.warn("The ServletRegistration API was not available at startup time. This may be due to a misconfiguration; "
-							+ "if you are using AbstractSecurityWebApplicationInitializer, please double-check the recommendations outlined in "
-							+ "https://docs.spring.io/spring-security/reference/servlet/configuration/java.html#abstractsecuritywebapplicationinitializer-with-spring-mvc");
-				matchers.add(new DeferredRequestMatcher((request) -> resolve(ant, mvc, request.getServletContext()),
-						mvc, ant));
-			}
+			matchers.add(new DeferredRequestMatcher((c) -> resolve(ant, mvc, c), mvc, ant));
 		}
 		return requestMatchers(matchers.toArray(new RequestMatcher[0]));
 	}
 
-	private static boolean isProgrammaticApiAvailable(ServletContext servletContext) {
-		try {
-			servletContext.getServletRegistrations();
-			return true;
-		}
-		catch (UnsupportedOperationException ex) {
-			return false;
-		}
-	}
-
 	private RequestMatcher resolve(AntPathRequestMatcher ant, MvcRequestMatcher mvc, ServletContext servletContext) {
 		Map<String, ? extends ServletRegistration> registrations = mappableServletRegistrations(servletContext);
 		if (registrations.isEmpty()) {
@@ -474,34 +454,29 @@ public abstract class AbstractRequestMatcherRegistry<C> {
 
 	static class DeferredRequestMatcher implements RequestMatcher {
 
-		final Function<HttpServletRequest, RequestMatcher> requestMatcherFactory;
+		final Function<ServletContext, RequestMatcher> requestMatcherFactory;
 
 		final AtomicReference<String> description = new AtomicReference<>();
 
-		volatile RequestMatcher requestMatcher;
-
-		DeferredRequestMatcher(Function<HttpServletRequest, RequestMatcher> resolver, RequestMatcher... candidates) {
-			this.requestMatcherFactory = (request) -> {
-				if (this.requestMatcher == null) {
-					synchronized (this) {
-						if (this.requestMatcher == null) {
-							this.requestMatcher = resolver.apply(request);
-						}
-					}
-				}
-				return this.requestMatcher;
-			};
+		final Map<ServletContext, RequestMatcher> requestMatchers = new ConcurrentHashMap<>();
+
+		DeferredRequestMatcher(Function<ServletContext, RequestMatcher> resolver, RequestMatcher... candidates) {
+			this.requestMatcherFactory = (sc) -> this.requestMatchers.computeIfAbsent(sc, resolver);
 			this.description.set("Deferred " + Arrays.toString(candidates));
 		}
 
+		RequestMatcher requestMatcher(ServletContext servletContext) {
+			return this.requestMatcherFactory.apply(servletContext);
+		}
+
 		@Override
 		public boolean matches(HttpServletRequest request) {
-			return this.requestMatcherFactory.apply(request).matches(request);
+			return this.requestMatcherFactory.apply(request.getServletContext()).matches(request);
 		}
 
 		@Override
 		public MatchResult matcher(HttpServletRequest request) {
-			return this.requestMatcherFactory.apply(request).matcher(request);
+			return this.requestMatcherFactory.apply(request.getServletContext()).matcher(request);
 		}
 
 		@Override

+ 6 - 4
config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2023 the original author or authors.
+ * Copyright 2002-2024 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.
@@ -303,11 +303,13 @@ public class AbstractRequestMatcherRegistryTests {
 			return requestMatchers;
 		}
 
-		private static List<RequestMatcher> unwrap(List<RequestMatcher> wrappedMatchers) {
+		private List<RequestMatcher> unwrap(List<RequestMatcher> wrappedMatchers) {
 			List<RequestMatcher> requestMatchers = new ArrayList<>();
 			for (RequestMatcher requestMatcher : wrappedMatchers) {
-				if (requestMatcher instanceof AbstractRequestMatcherRegistry.DeferredRequestMatcher) {
-					requestMatchers.add(((DeferredRequestMatcher) requestMatcher).requestMatcher);
+				if (requestMatcher instanceof DeferredRequestMatcher) {
+					DeferredRequestMatcher deferred = (DeferredRequestMatcher) requestMatcher;
+					WebApplicationContext web = (WebApplicationContext) getApplicationContext();
+					requestMatchers.add(deferred.requestMatcher(web.getServletContext()));
 				}
 				else {
 					requestMatchers.add(requestMatcher);

+ 2 - 2
config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeRequestsTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2022 the original author or authors.
+ * Copyright 2002-2024 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.
@@ -78,7 +78,7 @@ public class AuthorizeRequestsTests {
 	@BeforeEach
 	public void setup() {
 		this.servletContext = spy(MockServletContext.mvc());
-		this.request = new MockHttpServletRequest("GET", "");
+		this.request = new MockHttpServletRequest(this.servletContext, "GET", "");
 		this.request.setMethod("GET");
 		this.response = new MockHttpServletResponse();
 		this.chain = new MockFilterChain();

+ 2 - 2
config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecuritySecurityMatchersTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2022 the original author or authors.
+ * Copyright 2002-2024 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.
@@ -75,7 +75,7 @@ public class HttpSecuritySecurityMatchersTests {
 
 	@BeforeEach
 	public void setup() throws Exception {
-		this.request = new MockHttpServletRequest("GET", "");
+		this.request = new MockHttpServletRequest(MockServletContext.mvc(), "GET", "");
 		this.request.setMethod("GET");
 		this.response = new MockHttpServletResponse();
 		this.chain = new MockFilterChain();

+ 2 - 2
config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurerTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2022 the original author or authors.
+ * Copyright 2002-2024 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.
@@ -72,7 +72,7 @@ public class UrlAuthorizationConfigurerTests {
 
 	@BeforeEach
 	public void setup() {
-		this.request = new MockHttpServletRequest("GET", "");
+		this.request = new MockHttpServletRequest(MockServletContext.mvc(), "GET", "");
 		this.request.setMethod("GET");
 		this.response = new MockHttpServletResponse();
 		this.chain = new MockFilterChain();