mirror of
				https://github.com/spring-projects/spring-security.git
				synced 2025-10-31 14:48:54 +00:00 
			
		
		
		
	Merge branch '6.1.x'
This commit is contained in:
		
						commit
						8f5793afb1
					
				| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2017 the original author or authors. |  * Copyright 2002-2023 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. | ||||||
| @ -16,6 +16,7 @@ | |||||||
| 
 | 
 | ||||||
| package org.springframework.security.config.web.server; | package org.springframework.security.config.web.server; | ||||||
| 
 | 
 | ||||||
|  | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| 
 | 
 | ||||||
| import org.springframework.http.HttpMethod; | import org.springframework.http.HttpMethod; | ||||||
| @ -23,6 +24,8 @@ import org.springframework.security.web.server.util.matcher.OrServerWebExchangeM | |||||||
| import org.springframework.security.web.server.util.matcher.PathPatternParserServerWebExchangeMatcher; | import org.springframework.security.web.server.util.matcher.PathPatternParserServerWebExchangeMatcher; | ||||||
| import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher; | import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher; | ||||||
| import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers; | import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers; | ||||||
|  | import org.springframework.web.util.pattern.PathPattern; | ||||||
|  | import org.springframework.web.util.pattern.PathPatternParser; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * @author Rob Winch |  * @author Rob Winch | ||||||
| @ -62,7 +65,8 @@ public abstract class AbstractServerWebExchangeMatcherRegistry<T> { | |||||||
| 	 * {@link ServerWebExchangeMatcher} | 	 * {@link ServerWebExchangeMatcher} | ||||||
| 	 */ | 	 */ | ||||||
| 	public T pathMatchers(HttpMethod method, String... antPatterns) { | 	public T pathMatchers(HttpMethod method, String... antPatterns) { | ||||||
| 		return matcher(ServerWebExchangeMatchers.pathMatchers(method, antPatterns)); | 		List<PathPattern> pathPatterns = parsePatterns(antPatterns); | ||||||
|  | 		return matcher(ServerWebExchangeMatchers.pathMatchers(method, pathPatterns.toArray(new PathPattern[0]))); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| @ -74,7 +78,19 @@ public abstract class AbstractServerWebExchangeMatcherRegistry<T> { | |||||||
| 	 * {@link ServerWebExchangeMatcher} | 	 * {@link ServerWebExchangeMatcher} | ||||||
| 	 */ | 	 */ | ||||||
| 	public T pathMatchers(String... antPatterns) { | 	public T pathMatchers(String... antPatterns) { | ||||||
| 		return matcher(ServerWebExchangeMatchers.pathMatchers(antPatterns)); | 		List<PathPattern> pathPatterns = parsePatterns(antPatterns); | ||||||
|  | 		return matcher(ServerWebExchangeMatchers.pathMatchers(pathPatterns.toArray(new PathPattern[0]))); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private List<PathPattern> parsePatterns(String[] antPatterns) { | ||||||
|  | 		PathPatternParser parser = getPathPatternParser(); | ||||||
|  | 		List<PathPattern> pathPatterns = new ArrayList<>(antPatterns.length); | ||||||
|  | 		for (String pattern : antPatterns) { | ||||||
|  | 			pattern = parser.initFullPathPattern(pattern); | ||||||
|  | 			PathPattern pathPattern = parser.parse(pattern); | ||||||
|  | 			pathPatterns.add(pathPattern); | ||||||
|  | 		} | ||||||
|  | 		return pathPatterns; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| @ -96,6 +112,10 @@ public abstract class AbstractServerWebExchangeMatcherRegistry<T> { | |||||||
| 	 */ | 	 */ | ||||||
| 	protected abstract T registerMatcher(ServerWebExchangeMatcher matcher); | 	protected abstract T registerMatcher(ServerWebExchangeMatcher matcher); | ||||||
| 
 | 
 | ||||||
|  | 	protected PathPatternParser getPathPatternParser() { | ||||||
|  | 		return PathPatternParser.defaultInstance; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Associates a {@link ServerWebExchangeMatcher} instances | 	 * Associates a {@link ServerWebExchangeMatcher} instances | ||||||
| 	 * @param matcher the {@link ServerWebExchangeMatcher} instance | 	 * @param matcher the {@link ServerWebExchangeMatcher} instance | ||||||
|  | |||||||
| @ -191,9 +191,11 @@ import org.springframework.web.cors.reactive.CorsConfigurationSource; | |||||||
| import org.springframework.web.cors.reactive.CorsProcessor; | import org.springframework.web.cors.reactive.CorsProcessor; | ||||||
| import org.springframework.web.cors.reactive.CorsWebFilter; | import org.springframework.web.cors.reactive.CorsWebFilter; | ||||||
| import org.springframework.web.cors.reactive.DefaultCorsProcessor; | import org.springframework.web.cors.reactive.DefaultCorsProcessor; | ||||||
|  | import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping; | ||||||
| import org.springframework.web.server.ServerWebExchange; | import org.springframework.web.server.ServerWebExchange; | ||||||
| import org.springframework.web.server.WebFilter; | import org.springframework.web.server.WebFilter; | ||||||
| import org.springframework.web.server.WebFilterChain; | import org.springframework.web.server.WebFilterChain; | ||||||
|  | import org.springframework.web.util.pattern.PathPatternParser; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * A {@link ServerHttpSecurity} is similar to Spring Security's {@code HttpSecurity} but |  * A {@link ServerHttpSecurity} is similar to Spring Security's {@code HttpSecurity} but | ||||||
| @ -1661,6 +1663,18 @@ public class ServerHttpSecurity { | |||||||
| 		return null; | 		return null; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	private <T> T getBeanOrNull(String beanName, Class<T> requiredClass) { | ||||||
|  | 		if (this.context == null) { | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
|  | 		try { | ||||||
|  | 			return this.context.getBean(beanName, requiredClass); | ||||||
|  | 		} | ||||||
|  | 		catch (Exception ex) { | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	private <T> String[] getBeanNamesForTypeOrEmpty(Class<T> beanClass) { | 	private <T> String[] getBeanNamesForTypeOrEmpty(Class<T> beanClass) { | ||||||
| 		if (this.context == null) { | 		if (this.context == null) { | ||||||
| 			return new String[0]; | 			return new String[0]; | ||||||
| @ -1681,6 +1695,8 @@ public class ServerHttpSecurity { | |||||||
| 	 */ | 	 */ | ||||||
| 	public class AuthorizeExchangeSpec extends AbstractServerWebExchangeMatcherRegistry<AuthorizeExchangeSpec.Access> { | 	public class AuthorizeExchangeSpec extends AbstractServerWebExchangeMatcherRegistry<AuthorizeExchangeSpec.Access> { | ||||||
| 
 | 
 | ||||||
|  | 		private static final String REQUEST_MAPPING_HANDLER_MAPPING_BEAN_NAME = "requestMappingHandlerMapping"; | ||||||
|  | 
 | ||||||
| 		private DelegatingReactiveAuthorizationManager.Builder managerBldr = DelegatingReactiveAuthorizationManager | 		private DelegatingReactiveAuthorizationManager.Builder managerBldr = DelegatingReactiveAuthorizationManager | ||||||
| 				.builder(); | 				.builder(); | ||||||
| 
 | 
 | ||||||
| @ -1688,6 +1704,8 @@ public class ServerHttpSecurity { | |||||||
| 
 | 
 | ||||||
| 		private boolean anyExchangeRegistered; | 		private boolean anyExchangeRegistered; | ||||||
| 
 | 
 | ||||||
|  | 		private PathPatternParser pathPatternParser; | ||||||
|  | 
 | ||||||
| 		/** | 		/** | ||||||
| 		 * Allows method chaining to continue configuring the {@link ServerHttpSecurity} | 		 * Allows method chaining to continue configuring the {@link ServerHttpSecurity} | ||||||
| 		 * @return the {@link ServerHttpSecurity} to continue configuring | 		 * @return the {@link ServerHttpSecurity} to continue configuring | ||||||
| @ -1710,6 +1728,22 @@ public class ServerHttpSecurity { | |||||||
| 			return result; | 			return result; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		@Override | ||||||
|  | 		protected PathPatternParser getPathPatternParser() { | ||||||
|  | 			if (this.pathPatternParser != null) { | ||||||
|  | 				return this.pathPatternParser; | ||||||
|  | 			} | ||||||
|  | 			RequestMappingHandlerMapping requestMappingHandlerMapping = getBeanOrNull( | ||||||
|  | 					REQUEST_MAPPING_HANDLER_MAPPING_BEAN_NAME, RequestMappingHandlerMapping.class); | ||||||
|  | 			if (requestMappingHandlerMapping != null) { | ||||||
|  | 				this.pathPatternParser = requestMappingHandlerMapping.getPathPatternParser(); | ||||||
|  | 			} | ||||||
|  | 			if (this.pathPatternParser == null) { | ||||||
|  | 				this.pathPatternParser = PathPatternParser.defaultInstance; | ||||||
|  | 			} | ||||||
|  | 			return this.pathPatternParser; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		@Override | 		@Override | ||||||
| 		protected Access registerMatcher(ServerWebExchangeMatcher matcher) { | 		protected Access registerMatcher(ServerWebExchangeMatcher matcher) { | ||||||
| 			Assert.state(!this.anyExchangeRegistered, () -> "Cannot register " + matcher | 			Assert.state(!this.anyExchangeRegistered, () -> "Cannot register " + matcher | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2020 the original author or authors. |  * Copyright 2002-2023 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. | ||||||
| @ -42,8 +42,6 @@ public final class PathPatternParserServerWebExchangeMatcher implements ServerWe | |||||||
| 
 | 
 | ||||||
| 	private static final Log logger = LogFactory.getLog(PathPatternParserServerWebExchangeMatcher.class); | 	private static final Log logger = LogFactory.getLog(PathPatternParserServerWebExchangeMatcher.class); | ||||||
| 
 | 
 | ||||||
| 	private static final PathPatternParser DEFAULT_PATTERN_PARSER = new PathPatternParser(); |  | ||||||
| 
 |  | ||||||
| 	private final PathPattern pattern; | 	private final PathPattern pattern; | ||||||
| 
 | 
 | ||||||
| 	private final HttpMethod method; | 	private final HttpMethod method; | ||||||
| @ -60,7 +58,7 @@ public final class PathPatternParserServerWebExchangeMatcher implements ServerWe | |||||||
| 
 | 
 | ||||||
| 	public PathPatternParserServerWebExchangeMatcher(String pattern, HttpMethod method) { | 	public PathPatternParserServerWebExchangeMatcher(String pattern, HttpMethod method) { | ||||||
| 		Assert.notNull(pattern, "pattern cannot be null"); | 		Assert.notNull(pattern, "pattern cannot be null"); | ||||||
| 		this.pattern = DEFAULT_PATTERN_PARSER.parse(pattern); | 		this.pattern = parse(pattern); | ||||||
| 		this.method = method; | 		this.method = method; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -68,6 +66,12 @@ public final class PathPatternParserServerWebExchangeMatcher implements ServerWe | |||||||
| 		this(pattern, null); | 		this(pattern, null); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	private PathPattern parse(String pattern) { | ||||||
|  | 		PathPatternParser parser = PathPatternParser.defaultInstance; | ||||||
|  | 		pattern = parser.initFullPathPattern(pattern); | ||||||
|  | 		return parser.parse(pattern); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	@Override | 	@Override | ||||||
| 	public Mono<MatchResult> matches(ServerWebExchange exchange) { | 	public Mono<MatchResult> matches(ServerWebExchange exchange) { | ||||||
| 		ServerHttpRequest request = exchange.getRequest(); | 		ServerHttpRequest request = exchange.getRequest(); | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2017 the original author or authors. |  * Copyright 2002-2023 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. | ||||||
| @ -23,6 +23,7 @@ import reactor.core.publisher.Mono; | |||||||
| 
 | 
 | ||||||
| import org.springframework.http.HttpMethod; | import org.springframework.http.HttpMethod; | ||||||
| import org.springframework.web.server.ServerWebExchange; | import org.springframework.web.server.ServerWebExchange; | ||||||
|  | import org.springframework.web.util.pattern.PathPattern; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Provides factory methods for creating common {@link ServerWebExchangeMatcher} |  * Provides factory methods for creating common {@link ServerWebExchangeMatcher} | ||||||
| @ -59,6 +60,30 @@ public abstract class ServerWebExchangeMatchers { | |||||||
| 		return pathMatchers(null, patterns); | 		return pathMatchers(null, patterns); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Creates a matcher that matches on any of the provided {@link PathPattern}s. | ||||||
|  | 	 * @param pathPatterns the {@link PathPattern}s to match on | ||||||
|  | 	 * @return the matcher to use | ||||||
|  | 	 */ | ||||||
|  | 	public static ServerWebExchangeMatcher pathMatchers(PathPattern... pathPatterns) { | ||||||
|  | 		return pathMatchers(null, pathPatterns); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Creates a matcher that matches on the specific method and any of the provided | ||||||
|  | 	 * {@link PathPattern}s. | ||||||
|  | 	 * @param method the method to match on. If null, any method will be matched. | ||||||
|  | 	 * @param pathPatterns the {@link PathPattern}s to match on | ||||||
|  | 	 * @return the matcher to use | ||||||
|  | 	 */ | ||||||
|  | 	public static ServerWebExchangeMatcher pathMatchers(HttpMethod method, PathPattern... pathPatterns) { | ||||||
|  | 		List<ServerWebExchangeMatcher> matchers = new ArrayList<>(pathPatterns.length); | ||||||
|  | 		for (PathPattern pathPattern : pathPatterns) { | ||||||
|  | 			matchers.add(new PathPatternParserServerWebExchangeMatcher(pathPattern, method)); | ||||||
|  | 		} | ||||||
|  | 		return new OrServerWebExchangeMatcher(matchers); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Creates a matcher that will match on any of the provided matchers | 	 * Creates a matcher that will match on any of the provided matchers | ||||||
| 	 * @param matchers the matchers to match on | 	 * @param matchers the matchers to match on | ||||||
|  | |||||||
| @ -0,0 +1,40 @@ | |||||||
|  | /* | ||||||
|  |  * Copyright 2002-2023 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. | ||||||
|  |  * You may obtain a copy of the License at | ||||||
|  |  * | ||||||
|  |  *      https://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  |  * | ||||||
|  |  * Unless required by applicable law or agreed to in writing, software | ||||||
|  |  * distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |  * See the License for the specific language governing permissions and | ||||||
|  |  * limitations under the License. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package org.springframework.security.web.server.util.matcher; | ||||||
|  | 
 | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | 
 | ||||||
|  | import org.springframework.mock.http.server.reactive.MockServerHttpRequest; | ||||||
|  | import org.springframework.mock.web.server.MockServerWebExchange; | ||||||
|  | 
 | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Tests for {@link PathPatternParserServerWebExchangeMatcher} | ||||||
|  |  * | ||||||
|  |  * @author Marcus da Coregio | ||||||
|  |  */ | ||||||
|  | class PathPatternParserServerWebExchangeMatcherTests { | ||||||
|  | 
 | ||||||
|  | 	@Test | ||||||
|  | 	void matchesWhenConfiguredWithNoTrailingSlashAndPathContainsSlashThenMatches() { | ||||||
|  | 		PathPatternParserServerWebExchangeMatcher matcher = new PathPatternParserServerWebExchangeMatcher("user/**"); | ||||||
|  | 		MockServerHttpRequest request = MockServerHttpRequest.get("/user/test").build(); | ||||||
|  | 		assertThat(matcher.matches(MockServerWebExchange.from(request)).block().isMatch()).isTrue(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user