diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcChildContextConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcChildContextConfiguration.java index 16d42130c14..13fdbe6d39b 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcChildContextConfiguration.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcChildContextConfiguration.java @@ -39,6 +39,7 @@ import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint; import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoints; 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.SearchStrategy; import org.springframework.boot.autoconfigure.web.ErrorAttributes; import org.springframework.boot.autoconfigure.web.HttpMessageConverters; @@ -50,6 +51,7 @@ import org.springframework.boot.context.embedded.ErrorPage; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.HandlerAdapter; import org.springframework.web.servlet.HandlerMapping; @@ -133,40 +135,6 @@ public class EndpointWebMvcChildContextConfiguration { return adapter; } - @Bean - public HandlerMapping handlerMapping(MvcEndpoints endpoints, - ListableBeanFactory beanFactory) { - Set set = new HashSet(endpoints.getEndpoints()); - set.addAll(beanFactory.getBeansOfType(MvcEndpoint.class).values()); - EndpointHandlerMapping mapping = new EndpointHandlerMapping(set); - // In a child context we definitely want to see the parent endpoints - mapping.setDetectHandlerMethodsInAncestorContexts(true); - injectIntoSecurityFilter(beanFactory, mapping); - if (this.mappingCustomizers != null) { - for (EndpointHandlerMappingCustomizer customizer : this.mappingCustomizers) { - customizer.customize(mapping); - } - } - return mapping; - } - - private void injectIntoSecurityFilter(ListableBeanFactory beanFactory, - EndpointHandlerMapping mapping) { - // The parent context has the security filter, so we need to get it injected with - // our EndpointHandlerMapping if we can. - if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, - ManagementWebSecurityConfigurerAdapter.class).length == 1) { - ManagementWebSecurityConfigurerAdapter bean = beanFactory - .getBean(ManagementWebSecurityConfigurerAdapter.class); - bean.setEndpointHandlerMapping(mapping); - } - else { - logger.warn("No single bean of type " - + ManagementWebSecurityConfigurerAdapter.class.getSimpleName() - + " found (this might make some endpoints inaccessible without authentication)"); - } - } - /* * The error controller is present but not mapped as an endpoint in this context * because of the DispatcherServlet having had it's HandlerMapping explicitly @@ -177,6 +145,71 @@ public class EndpointWebMvcChildContextConfiguration { return new ManagementErrorEndpoint(this.errorPath, errorAttributes); } + @Configuration + @ConditionalOnMissingClass(WebSecurityConfigurerAdapter.class) + static class EndpointHandlerMappingSimpleConfiguration { + + @Autowired(required = false) + private List mappingCustomizers; + + @Bean + public HandlerMapping handlerMapping(MvcEndpoints endpoints, + ListableBeanFactory beanFactory) { + + EndpointHandlerMapping mapping = doCreateEndpointHandlerMapping(endpoints, beanFactory); + if (this.mappingCustomizers != null) { + for (EndpointHandlerMappingCustomizer customizer : this.mappingCustomizers) { + customizer.customize(mapping); + } + } + return mapping; + } + + protected EndpointHandlerMapping doCreateEndpointHandlerMapping(MvcEndpoints endpoints, + ListableBeanFactory beanFactory) { + Set set = new HashSet(endpoints.getEndpoints()); + set.addAll(beanFactory.getBeansOfType(MvcEndpoint.class).values()); + EndpointHandlerMapping mapping = new EndpointHandlerMapping(set); + // In a child context we definitely want to see the parent endpoints + mapping.setDetectHandlerMethodsInAncestorContexts(true); + return mapping; + } + + } + + @Configuration + @ConditionalOnClass(WebSecurityConfigurerAdapter.class) + static class EndpointHandlerMappingSecurityConfiguration + extends EndpointHandlerMappingSimpleConfiguration { + + @Override + protected EndpointHandlerMapping doCreateEndpointHandlerMapping(MvcEndpoints endpoints, + ListableBeanFactory beanFactory) { + + EndpointHandlerMapping mapping = super.doCreateEndpointHandlerMapping(endpoints, beanFactory); + injectIntoSecurityFilter(beanFactory, mapping); + return mapping; + } + + private void injectIntoSecurityFilter(ListableBeanFactory beanFactory, + EndpointHandlerMapping mapping) { + // The parent context has the security filter, so we need to get it injected with + // our EndpointHandlerMapping if we can. + if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, + ManagementWebSecurityConfigurerAdapter.class).length == 1) { + ManagementWebSecurityConfigurerAdapter bean = beanFactory + .getBean(ManagementWebSecurityConfigurerAdapter.class); + bean.setEndpointHandlerMapping(mapping); + } + else { + logger.warn("No single bean of type " + + ManagementWebSecurityConfigurerAdapter.class.getSimpleName() + + " found (this might make some endpoints inaccessible without authentication)"); + } + } + + } + @Configuration @ConditionalOnClass({ EnableWebSecurity.class, Filter.class }) @ConditionalOnBean(name = "springSecurityFilterChain", search = SearchStrategy.PARENTS)