Allow actuator endpoints to be used with mvcMatchers

This commit changes AbstractWebMvcEndpointHandlerMapping to
be a MatchableHandlerMapping. Additionally, EndpointRequest,
now delegates to MvcRequestMatcher for Spring MVC applications.

For all other applications, AntPathRequestMatcher is used as
a delegate.

Closes gh-13962
This commit is contained in:
Madhura Bhave
2018-07-31 13:51:19 -07:00
parent a75a84781e
commit b93c2b9a9f
11 changed files with 345 additions and 18 deletions

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2012-2018 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
*
* http://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.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
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.
*
* @author Madhura Bhave
*/
public class MvcRequestMatcherProvider implements RequestMatcherProvider {
private final HandlerMappingIntrospector introspector;
public MvcRequestMatcherProvider(HandlerMappingIntrospector introspector) {
this.introspector = introspector;
}
@Override
public RequestMatcher getRequestMatcher(String pattern) {
return new MvcRequestMatcher(this.introspector, pattern);
}
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2012-2018 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
*
* http://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.springframework.security.web.util.matcher.RequestMatcher;
/**
* Interface that can be used to provide a {@link RequestMatcher} that can be used with
* Spring Security.
*
* @author Madhura Bhave
* @since 2.0.5
*/
@FunctionalInterface
public interface RequestMatcherProvider {
RequestMatcher getRequestMatcher(String pattern);
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2012-2018 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
*
* http://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.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
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, DispatcherServlet.class })
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnBean(HandlerMappingIntrospector.class)
public class SecurityRequestMatcherProviderAutoConfiguration {
@Bean
public RequestMatcherProvider requestMatcherProvider(
HandlerMappingIntrospector introspector) {
return new MvcRequestMatcherProvider(introspector);
}
}

View File

@@ -97,6 +97,7 @@ 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,\

View File

@@ -0,0 +1,95 @@
/*
* Copyright 2012-2018 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
*
* http://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.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))
.withUserConfiguration(TestConfiguration.class);
@Test
public void registersMvcRequestMatcherProviderForIfMvcPresent() {
this.contextRunner.run((context) -> assertThat(context)
.hasSingleBean(MvcRequestMatcherProvider.class));
}
@Test
public void mvcRequestMatcherProviderConditionalOnWebApplication() {
new ApplicationContextRunner()
.withConfiguration(AutoConfigurations
.of(SecurityRequestMatcherProviderAutoConfiguration.class))
.withUserConfiguration(TestConfiguration.class)
.run((context) -> assertThat(context)
.doesNotHaveBean(MvcRequestMatcherProvider.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 mvcRequestMatcherProviderConditionalOnRequestMatcherClass() {
this.contextRunner
.withClassLoader(new FilteredClassLoader(
"org.springframework.security.web.util.matcher.RequestMatcher"))
.run((context) -> assertThat(context)
.doesNotHaveBean(MvcRequestMatcherProvider.class));
}
@Test
public void mvcRequestMatcherProviderConditionalOnHandlerMappingIntrospectorBean() {
new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations
.of(SecurityRequestMatcherProviderAutoConfiguration.class))
.run((context) -> assertThat(context)
.doesNotHaveBean(MvcRequestMatcherProvider.class));
}
@Configuration
static class TestConfiguration {
@Bean
public HandlerMappingIntrospector introspector() {
return new HandlerMappingIntrospector();
}
}
}