Fix management endpoint without Spring Security
The method 'injectIntoSecurityFilter' added In 3c1e48c assumes that
Spring security is in the classpath so any management endpoints that are
deployed on a different port requires Spring Security all the sudden.
This commit separates the creating of the EndpointHandlerMapping in two
mutually exclusive @Configuration: one that is triggered if Spring
Security is not in the classpath and one that is triggered if Spring
Security is in the classpath. The latter apply the security filter in the
endpoint mapping if it exists.
Fixes gh-2124
This commit is contained in:
parent
f8141cbb95
commit
e96f75fdc1
|
|
@ -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<MvcEndpoint> set = new HashSet<MvcEndpoint>(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<EndpointHandlerMappingCustomizer> 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<MvcEndpoint> set = new HashSet<MvcEndpoint>(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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue