EndpointRequest should match @ServletEndpoint
This commit also changes the request matcher for MVC endpoints to use an AntPathRequestMatcher instead of an MvcRequestMatcher. The endpoint is always available under the mapped endpoint path and this way the same matcher can be used for both MVC and Jersey. Fixes gh-17912 Co-authored-by: Phillip Webb <pwebb@pivotal.io>
This commit is contained in:
@@ -13,30 +13,31 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.security.servlet;
|
||||
|
||||
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
||||
|
||||
/**
|
||||
* {@link RequestMatcherProvider} that provides an {@link MvcRequestMatcher} that can be
|
||||
* used for Spring MVC applications.
|
||||
* {@link RequestMatcherProvider} that provides an {@link AntPathRequestMatcher}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @since 2.0.5
|
||||
* @since 2.1.8
|
||||
*/
|
||||
public class MvcRequestMatcherProvider implements RequestMatcherProvider {
|
||||
public class AntPathRequestMatcherProvider implements RequestMatcherProvider {
|
||||
|
||||
private final HandlerMappingIntrospector introspector;
|
||||
private final Function<String, String> pathFactory;
|
||||
|
||||
public MvcRequestMatcherProvider(HandlerMappingIntrospector introspector) {
|
||||
this.introspector = introspector;
|
||||
public AntPathRequestMatcherProvider(Function<String, String> pathFactory) {
|
||||
this.pathFactory = pathFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestMatcher getRequestMatcher(String pattern) {
|
||||
return new MvcRequestMatcher(this.introspector, pattern);
|
||||
return new AntPathRequestMatcher(this.pathFactory.apply(pattern));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,7 +25,9 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @since 2.0.7
|
||||
* @deprecated since 2.1.8 in favor of {@link AntPathRequestMatcher}
|
||||
*/
|
||||
@Deprecated
|
||||
public class JerseyRequestMatcherProvider implements RequestMatcherProvider {
|
||||
|
||||
private final JerseyApplicationPath jerseyApplicationPath;
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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.boot.autoconfigure.security.servlet;
|
||||
|
||||
import org.glassfish.jersey.server.ResourceConfig;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.JerseyApplicationPath;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
||||
|
||||
/**
|
||||
* Auto-configuration for {@link RequestMatcherProvider}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @since 2.0.5
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ RequestMatcher.class })
|
||||
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
|
||||
public class SecurityRequestMatcherProviderAutoConfiguration {
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(DispatcherServlet.class)
|
||||
@ConditionalOnBean(HandlerMappingIntrospector.class)
|
||||
public static class MvcRequestMatcherConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnClass(DispatcherServlet.class)
|
||||
public RequestMatcherProvider requestMatcherProvider(HandlerMappingIntrospector introspector) {
|
||||
return new MvcRequestMatcherProvider(introspector);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(ResourceConfig.class)
|
||||
@ConditionalOnMissingClass("org.springframework.web.servlet.DispatcherServlet")
|
||||
@ConditionalOnBean(JerseyApplicationPath.class)
|
||||
public static class JerseyRequestMatcherConfiguration {
|
||||
|
||||
@Bean
|
||||
public RequestMatcherProvider requestMatcherProvider(JerseyApplicationPath applicationPath) {
|
||||
return new JerseyRequestMatcherProvider(applicationPath);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -100,7 +100,6 @@ org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.reactor.core.ReactorCoreAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.security.servlet.SecurityRequestMatcherProviderAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2019 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.boot.autoconfigure.security.servlet;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.JerseyApplicationPath;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link SecurityRequestMatcherProviderAutoConfiguration}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class SecurityRequestMatcherProviderAutoConfigurationTests {
|
||||
|
||||
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(SecurityRequestMatcherProviderAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void configurationConditionalOnWebApplication() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(SecurityRequestMatcherProviderAutoConfiguration.class))
|
||||
.withUserConfiguration(TestMvcConfiguration.class)
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(RequestMatcherProvider.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configurationConditionalOnRequestMatcherClass() {
|
||||
this.contextRunner
|
||||
.withClassLoader(
|
||||
new FilteredClassLoader("org.springframework.security.web.util.matcher.RequestMatcher"))
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(RequestMatcherProvider.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registersMvcRequestMatcherProviderIfMvcPresent() {
|
||||
this.contextRunner.withUserConfiguration(TestMvcConfiguration.class).run((context) -> assertThat(context)
|
||||
.getBean(RequestMatcherProvider.class).isInstanceOf(MvcRequestMatcherProvider.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registersRequestMatcherForJerseyProviderIfJerseyPresentAndMvcAbsent() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader("org.springframework.web.servlet.DispatcherServlet"))
|
||||
.withUserConfiguration(TestJerseyConfiguration.class).run((context) -> assertThat(context)
|
||||
.getBean(RequestMatcherProvider.class).isInstanceOf(JerseyRequestMatcherProvider.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mvcRequestMatcherProviderConditionalOnDispatcherServletClass() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader("org.springframework.web.servlet.DispatcherServlet"))
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(MvcRequestMatcherProvider.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jerseyRequestMatcherProviderConditionalOnResourceConfigClass() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader("org.glassfish.jersey.server.ResourceConfig"))
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(JerseyRequestMatcherProvider.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mvcRequestMatcherProviderConditionalOnHandlerMappingIntrospectorBean() {
|
||||
new WebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(SecurityRequestMatcherProviderAutoConfiguration.class))
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(MvcRequestMatcherProvider.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jerseyRequestMatcherProviderConditionalOnJerseyApplicationPathBean() {
|
||||
new WebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(SecurityRequestMatcherProviderAutoConfiguration.class))
|
||||
.withClassLoader(new FilteredClassLoader("org.springframework.web.servlet.DispatcherServlet"))
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(JerseyRequestMatcherProvider.class));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class TestMvcConfiguration {
|
||||
|
||||
@Bean
|
||||
public HandlerMappingIntrospector introspector() {
|
||||
return new HandlerMappingIntrospector();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class TestJerseyConfiguration {
|
||||
|
||||
@Bean
|
||||
public JerseyApplicationPath jerseyApplicationPath() {
|
||||
return () -> "/admin";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user