Temporarily remove security matchers
Temporarily back out `SpringBootSecurity` to enable easier package refactoring. See gh-10261
This commit is contained in:
parent
ecb8461e8c
commit
0f99b29b1a
|
@ -16,14 +16,10 @@
|
|||
|
||||
package org.springframework.boot.autoconfigure.security;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorController;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.endpoint.DefaultEndpointPathResolver;
|
||||
import org.springframework.boot.endpoint.EndpointPathResolver;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
@ -56,20 +52,6 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
|
|||
AuthenticationManagerConfiguration.class, SecurityDataConfiguration.class })
|
||||
public class SecurityAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EndpointPathResolver endpointPathResolver() {
|
||||
return new DefaultEndpointPathResolver();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SpringBootSecurity springBootSecurity(
|
||||
EndpointPathResolver endpointPathResolver,
|
||||
ObjectProvider<ErrorController> errorController) {
|
||||
return new SpringBootSecurity(endpointPathResolver,
|
||||
errorController.getIfAvailable());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(AuthenticationEventPublisher.class)
|
||||
public DefaultAuthenticationEventPublisher authenticationEventPublisher(
|
||||
|
|
|
@ -1,141 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012-2017 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorController;
|
||||
import org.springframework.boot.endpoint.Endpoint;
|
||||
import org.springframework.boot.endpoint.EndpointPathResolver;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides request matchers that can be used to configure security for static resources
|
||||
* and the error controller path in a custom {@link WebSecurityConfigurerAdapter}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public final class SpringBootSecurity {
|
||||
|
||||
/**
|
||||
* Used as a wildcard matcher for all endpoints.
|
||||
*/
|
||||
public final static String ALL_ENDPOINTS = "**";
|
||||
|
||||
private static String[] STATIC_RESOURCES = new String[] { "/css/**", "/js/**",
|
||||
"/images/**", "/webjars/**", "/**/favicon.ico" };
|
||||
|
||||
private final EndpointPathResolver endpointPathResolver;
|
||||
|
||||
private final ErrorController errorController;
|
||||
|
||||
SpringBootSecurity(EndpointPathResolver endpointPathResolver,
|
||||
ErrorController errorController) {
|
||||
this.endpointPathResolver = endpointPathResolver;
|
||||
this.errorController = errorController;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link RequestMatcher} that matches on all endpoint paths with given ids.
|
||||
* @param ids the endpoint ids
|
||||
* @return the request matcher
|
||||
*/
|
||||
public RequestMatcher endpointIds(String... ids) {
|
||||
Assert.notEmpty(ids, "At least one endpoint id must be specified.");
|
||||
List<String> pathList = Arrays.asList(ids);
|
||||
if (pathList.contains(ALL_ENDPOINTS)) {
|
||||
return new AntPathRequestMatcher(
|
||||
this.endpointPathResolver.resolvePath(ALL_ENDPOINTS), null);
|
||||
}
|
||||
return getEndpointsRequestMatcher(pathList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link RequestMatcher} that matches on all endpoint paths for the given
|
||||
* classes with the {@link Endpoint} annotation.
|
||||
* @param endpoints the endpoint classes
|
||||
* @return the request matcher
|
||||
*/
|
||||
public RequestMatcher endpoints(Class<?>... endpoints) {
|
||||
Assert.notEmpty(endpoints, "At least one endpoint must be specified.");
|
||||
List<String> paths = Arrays.stream(endpoints).map((e) -> {
|
||||
if (e.isAnnotationPresent(Endpoint.class)) {
|
||||
return e.getAnnotation(Endpoint.class).id();
|
||||
}
|
||||
throw new IllegalArgumentException(
|
||||
"Only classes annotated with @Endpoint are supported.");
|
||||
}).collect(Collectors.toList());
|
||||
return getEndpointsRequestMatcher(paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link RequestMatcher} that matches on all static resources.
|
||||
* @return the request matcher
|
||||
*/
|
||||
public RequestMatcher staticResources() {
|
||||
return getRequestMatcher(STATIC_RESOURCES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link RequestMatcher} that matches on the {@link ErrorController} path,
|
||||
* if present.
|
||||
* @return the request matcher
|
||||
*/
|
||||
public RequestMatcher error() {
|
||||
if (this.errorController == null) {
|
||||
throw new IllegalStateException(
|
||||
"Path for error controller could not be determined.");
|
||||
}
|
||||
String path = normalizePath(this.errorController.getErrorPath());
|
||||
return new AntPathRequestMatcher(path + "/**", null);
|
||||
}
|
||||
|
||||
private RequestMatcher getEndpointsRequestMatcher(List<String> ids) {
|
||||
List<RequestMatcher> matchers = new ArrayList<>();
|
||||
for (String id : ids) {
|
||||
String path = this.endpointPathResolver.resolvePath(id);
|
||||
matchers.add(new AntPathRequestMatcher(path + "/**", null));
|
||||
}
|
||||
return new OrRequestMatcher(matchers);
|
||||
}
|
||||
|
||||
private static RequestMatcher getRequestMatcher(String... paths) {
|
||||
List<RequestMatcher> matchers = new ArrayList<>();
|
||||
for (String path : paths) {
|
||||
matchers.add(new AntPathRequestMatcher(path, null));
|
||||
}
|
||||
return new OrRequestMatcher(matchers);
|
||||
}
|
||||
|
||||
private String normalizePath(String errorPath) {
|
||||
String result = StringUtils.cleanPath(errorPath);
|
||||
if (!result.startsWith("/")) {
|
||||
result = "/" + result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,178 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012-2017 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;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorController;
|
||||
import org.springframework.boot.endpoint.Endpoint;
|
||||
import org.springframework.boot.endpoint.EndpointPathResolver;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link SpringBootSecurity}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class SpringBootSecurityTests {
|
||||
|
||||
private SpringBootSecurity bootSecurity;
|
||||
|
||||
private EndpointPathResolver endpointPathResolver = new TestEndpointPathResolver();
|
||||
|
||||
private ErrorController errorController = new TestErrorController();
|
||||
|
||||
private MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
private static String[] STATIC_RESOURCES = new String[] { "/css/**", "/js/**",
|
||||
"/images/**", "/webjars/**", "/**/favicon.ico" };
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.bootSecurity = new SpringBootSecurity(this.endpointPathResolver,
|
||||
this.errorController);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void endpointIdsShouldThrowIfNoEndpointPaths() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("At least one endpoint id must be specified.");
|
||||
this.bootSecurity.endpointIds();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void endpointIdsShouldReturnRequestMatcherWithEndpointPaths()
|
||||
throws Exception {
|
||||
RequestMatcher requestMatcher = this.bootSecurity.endpointIds("id-1", "id-2");
|
||||
assertThat(requestMatcher).isInstanceOf(OrRequestMatcher.class);
|
||||
this.request.setServletPath("/test/id-1");
|
||||
assertThat(requestMatcher.matches(this.request)).isTrue();
|
||||
this.request.setServletPath("/test/id-2");
|
||||
assertThat(requestMatcher.matches(this.request)).isTrue();
|
||||
this.request.setServletPath("/test/other-id");
|
||||
assertThat(requestMatcher.matches(this.request)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void endpointIdsShouldReturnRequestMatcherWithAllEndpointPaths()
|
||||
throws Exception {
|
||||
RequestMatcher requestMatcher = this.bootSecurity
|
||||
.endpointIds(SpringBootSecurity.ALL_ENDPOINTS);
|
||||
this.request.setServletPath("/test/id-1");
|
||||
assertThat(requestMatcher.matches(this.request)).isTrue();
|
||||
this.request.setServletPath("/test/id-2");
|
||||
assertThat(requestMatcher.matches(this.request)).isTrue();
|
||||
this.request.setServletPath("/test/other-id");
|
||||
assertThat(requestMatcher.matches(this.request)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void endpointsShouldReturnRequestMatcherWithEndpointPaths() throws Exception {
|
||||
RequestMatcher requestMatcher = this.bootSecurity.endpoints(TestEndpoint1.class);
|
||||
assertThat(requestMatcher).isInstanceOf(OrRequestMatcher.class);
|
||||
this.request.setServletPath("/test/id-1");
|
||||
assertThat(requestMatcher.matches(this.request)).isTrue();
|
||||
this.request.setServletPath("/test/id-2");
|
||||
assertThat(requestMatcher.matches(this.request)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void endpointsShouldThrowIfNoEndpointPaths() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("At least one endpoint must be specified.");
|
||||
this.bootSecurity.endpoints();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void endpointsShouldThrowExceptionWhenClassNotEndpoint() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Only classes annotated with @Endpoint are supported.");
|
||||
this.bootSecurity.endpoints(FakeEndpoint.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void staticResourcesShouldReturnRequestMatcherWithStaticResources()
|
||||
throws Exception {
|
||||
RequestMatcher requestMatcher = this.bootSecurity.staticResources();
|
||||
assertThat(requestMatcher).isInstanceOf(OrRequestMatcher.class);
|
||||
for (String resource : STATIC_RESOURCES) {
|
||||
this.request.setServletPath(resource);
|
||||
assertThat(requestMatcher.matches(this.request)).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void errorShouldReturnRequestMatcherWithErrorControllerPath()
|
||||
throws Exception {
|
||||
RequestMatcher requestMatcher = this.bootSecurity.error();
|
||||
assertThat(requestMatcher).isInstanceOf(AntPathRequestMatcher.class);
|
||||
this.request.setServletPath("/test/error");
|
||||
assertThat(requestMatcher.matches(this.request)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void errorShouldThrowExceptionWhenNoErrorController() throws Exception {
|
||||
this.thrown.expect(IllegalStateException.class);
|
||||
this.thrown.expectMessage("Path for error controller could not be determined.");
|
||||
this.bootSecurity = new SpringBootSecurity(this.endpointPathResolver, null);
|
||||
this.bootSecurity.error();
|
||||
}
|
||||
|
||||
static class TestEndpointPathResolver implements EndpointPathResolver {
|
||||
|
||||
@Override
|
||||
public String resolvePath(String endpointId) {
|
||||
return "/test/" + endpointId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class TestErrorController implements ErrorController {
|
||||
|
||||
@Override
|
||||
public String getErrorPath() {
|
||||
return "/test/error";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Endpoint(id = "id-1")
|
||||
static class TestEndpoint1 {
|
||||
|
||||
}
|
||||
|
||||
@Endpoint(id = "id-2")
|
||||
static class TestEndpoint2 {
|
||||
|
||||
}
|
||||
|
||||
static class FakeEndpoint {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package sample.actuator.customsecurity;
|
||||
|
||||
import org.springframework.boot.autoconfigure.security.SpringBootSecurity;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
|
@ -9,12 +8,6 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
|
|||
@Configuration
|
||||
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
|
||||
private SpringBootSecurity bootSecurity;
|
||||
|
||||
public SecurityConfiguration(SpringBootSecurity bootSecurity) {
|
||||
this.bootSecurity = bootSecurity;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.inMemoryAuthentication().withUser("user").password("password")
|
||||
|
@ -24,18 +17,18 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
|||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
|
||||
// FIXME
|
||||
// @formatter:off
|
||||
http.authorizeRequests()
|
||||
.requestMatchers(this.bootSecurity.endpointIds("status", "info")).permitAll()
|
||||
.requestMatchers(this.bootSecurity.endpointIds(SpringBootSecurity.ALL_ENDPOINTS)).hasRole("ACTUATOR")
|
||||
.requestMatchers(this.bootSecurity.staticResources()).permitAll()
|
||||
.antMatchers("/foo").permitAll()
|
||||
.antMatchers("/**").hasRole("USER")
|
||||
.and()
|
||||
.cors()
|
||||
.and()
|
||||
.httpBasic();
|
||||
// http.authorizeRequests()
|
||||
// .requestMatchers(endpointIds("status", "info")).permitAll()
|
||||
// .requestMatchers(endpointIds(SpringBootSecurity.ALL_ENDPOINTS)).hasRole("ACTUATOR")
|
||||
// .requestMatchers(staticResources()).permitAll()
|
||||
// .antMatchers("/foo").permitAll()
|
||||
// .antMatchers("/**").hasRole("USER")
|
||||
// .and()
|
||||
// .cors()
|
||||
// .and()
|
||||
// .httpBasic();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package sample.secure.oauth2.actuator;
|
||||
|
||||
import org.springframework.boot.autoconfigure.security.SpringBootSecurity;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
|
@ -15,19 +14,14 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
|
|||
@Order(2) // before the resource server configuration
|
||||
public class ActuatorSecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
|
||||
private final SpringBootSecurity springBootSecurity;
|
||||
|
||||
public ActuatorSecurityConfiguration(SpringBootSecurity springBootSecurity) {
|
||||
this.springBootSecurity = springBootSecurity;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
// FIXME
|
||||
// @formatter:off
|
||||
http.requestMatcher(this.springBootSecurity.endpointIds(SpringBootSecurity.ALL_ENDPOINTS)).authorizeRequests()
|
||||
.antMatchers("/**").authenticated()
|
||||
.and()
|
||||
.httpBasic();
|
||||
// http.requestMatcher(ALL_ENDPOINTS).authorizeRequests()
|
||||
// .antMatchers("/**").authenticated()
|
||||
// .and()
|
||||
// .httpBasic();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ import java.util.Date;
|
|||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.security.SpringBootSecurity;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
|
@ -103,17 +102,11 @@ public class SampleMethodSecurityApplication implements WebMvcConfigurer {
|
|||
@Order(1)
|
||||
protected static class ActuatorSecurity extends WebSecurityConfigurerAdapter {
|
||||
|
||||
private final SpringBootSecurity springBootSecurity;
|
||||
|
||||
public ActuatorSecurity(SpringBootSecurity springBootSecurity) {
|
||||
this.springBootSecurity = springBootSecurity;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.requestMatcher(
|
||||
this.springBootSecurity.endpointIds(SpringBootSecurity.ALL_ENDPOINTS))
|
||||
.authorizeRequests().anyRequest().authenticated().and().httpBasic();
|
||||
// FIXME
|
||||
// http.requestMatcher(ALL_ENDPOINTS)
|
||||
// .authorizeRequests().anyRequest().authenticated().and().httpBasic();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ import java.util.Date;
|
|||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.security.SpringBootSecurity;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
|
@ -61,22 +60,17 @@ public class SampleWebSecureApplication implements WebMvcConfigurer {
|
|||
@Configuration
|
||||
protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter {
|
||||
|
||||
private final SpringBootSecurity springBootSecurity;
|
||||
|
||||
public ApplicationSecurity(SpringBootSecurity springBootSecurity) {
|
||||
this.springBootSecurity = springBootSecurity;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
// FIXME
|
||||
// @formatter:off
|
||||
http.authorizeRequests()
|
||||
.requestMatchers(this.springBootSecurity.staticResources()).permitAll()
|
||||
.anyRequest().fullyAuthenticated()
|
||||
.and()
|
||||
.formLogin().loginPage("/login").failureUrl("/login?error").permitAll()
|
||||
.and()
|
||||
.logout().permitAll();
|
||||
// http.authorizeRequests()
|
||||
// .requestMatchers(staticResources()).permitAll()
|
||||
// .anyRequest().fullyAuthenticated()
|
||||
// .and()
|
||||
// .formLogin().loginPage("/login").failureUrl("/login?error").permitAll()
|
||||
// .and()
|
||||
// .logout().permitAll();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue