This commit is contained in:
Phillip Webb
2017-08-28 15:29:36 -07:00
parent b02edd2e81
commit 2c97d3a5e9
143 changed files with 689 additions and 655 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* 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.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* 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.

View File

@@ -50,12 +50,12 @@ import org.springframework.util.ReflectionUtils;
/**
* Configuration for a Spring Security in-memory {@link AuthenticationManager}. Can be
* disabled by providing a bean of type {@link AuthenticationManager}, {@link AuthenticationProvider}
* or {@link UserDetailsService}. The value provided by this configuration will become the "global"
* authentication manager (from Spring Security), or the parent of the global instance.
* Thus it acts as a fallback when no others are provided, is used by method security if
* enabled, and as a parent authentication manager for "local" authentication managers in
* individual filter chains.
* disabled by providing a bean of type {@link AuthenticationManager},
* {@link AuthenticationProvider} or {@link UserDetailsService}. The value provided by
* this configuration will become the "global" authentication manager (from Spring
* Security), or the parent of the global instance. Thus it acts as a fallback when no
* others are provided, is used by method security if enabled, and as a parent
* authentication manager for "local" authentication managers in individual filter chains.
*
* @author Dave Syer
* @author Rob Winch
@@ -63,8 +63,8 @@ import org.springframework.util.ReflectionUtils;
*/
@Configuration
@ConditionalOnBean(ObjectPostProcessor.class)
@ConditionalOnMissingBean({ AuthenticationManager.class,
AuthenticationProvider.class, UserDetailsService.class})
@ConditionalOnMissingBean({ AuthenticationManager.class, AuthenticationProvider.class,
UserDetailsService.class })
@Order(0)
public class AuthenticationManagerConfiguration {
@@ -102,8 +102,8 @@ public class AuthenticationManagerConfiguration {
* {@link GlobalAuthenticationConfigurerAdapter#init(AuthenticationManagerBuilder)}
* exists that adds a {@link SecurityConfigurer} to the
* {@link AuthenticationManagerBuilder}.</li>
* <li>{@link AuthenticationManagerConfiguration}
* adds {@link SpringBootAuthenticationConfigurerAdapter} so it is after the
* <li>{@link AuthenticationManagerConfiguration} adds
* {@link SpringBootAuthenticationConfigurerAdapter} so it is after the
* {@link SecurityConfigurer} in the first step.</li>
* <li>We then can default an {@link AuthenticationProvider} if necessary. Note we can
* only invoke the
@@ -169,10 +169,9 @@ public class AuthenticationManagerConfiguration {
return;
}
String password = UUID.randomUUID().toString();
logger.info(String.format("%n%nUsing default security password: %s%n",
password));
withUser("user").password(password)
.roles();
logger.info(
String.format("%n%nUsing default security password: %s%n", password));
withUser("user").password(password).roles();
setField(auth, "defaultUserDetailsService", getUserDetailsService());
super.configure(auth);
}

View File

@@ -63,9 +63,11 @@ public class SecurityAutoConfiguration {
}
@Bean
public SpringBootSecurity springBootSecurity(EndpointPathResolver endpointPathResolver,
public SpringBootSecurity springBootSecurity(
EndpointPathResolver endpointPathResolver,
ObjectProvider<ErrorController> errorController) {
return new SpringBootSecurity(endpointPathResolver, errorController.getIfAvailable());
return new SpringBootSecurity(endpointPathResolver,
errorController.getIfAvailable());
}
@Bean

View File

@@ -73,8 +73,7 @@ public class SecurityFilterAutoConfiguration {
return null;
}
return securityProperties.getFilterDispatcherTypes().stream()
.map((type) -> DispatcherType.valueOf(type.name()))
.collect(Collectors
.map((type) -> DispatcherType.valueOf(type.name())).collect(Collectors
.collectingAndThen(Collectors.toSet(), EnumSet::copyOf));
}

View File

@@ -66,8 +66,8 @@ public class SecurityProperties implements SecurityPrerequisite {
/**
* Security filter chain dispatcher types.
*/
private Set<DispatcherType> filterDispatcherTypes = new HashSet<>(Arrays.asList(
DispatcherType.ASYNC, DispatcherType.ERROR, DispatcherType.REQUEST));
private Set<DispatcherType> filterDispatcherTypes = new HashSet<>(Arrays
.asList(DispatcherType.ASYNC, DispatcherType.ERROR, DispatcherType.REQUEST));
public Basic getBasic() {
return this.basic;

View File

@@ -31,7 +31,6 @@ 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}.
@@ -68,8 +67,8 @@ public final class SpringBootSecurity {
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 new AntPathRequestMatcher(
this.endpointPathResolver.resolvePath(ALL_ENDPOINTS), null);
}
return getEndpointsRequestMatcher(pathList);
}
@@ -140,4 +139,3 @@ public final class SpringBootSecurity {
}
}

View File

@@ -29,10 +29,10 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
/**
* The default configuration for web security. It relies on Spring Security's
* content-negotiation strategy to determine what sort of authentication to use.
* If the user specifies their own {@link WebSecurityConfigurerAdapter}, this will
* back-off completely and the users should specify all the bits that they want to
* configure as part of the custom security configuration.
* content-negotiation strategy to determine what sort of authentication to use. If the
* user specifies their own {@link WebSecurityConfigurerAdapter}, this will back-off
* completely and the users should specify all the bits that they want to configure as
* part of the custom security configuration.
*
* @author Madhura Bhave
* @since 2.0.0
@@ -52,6 +52,7 @@ public class SpringBootWebSecurityConfiguration {
super.configure(http);
http.csrf().disable();
}
}
}

View File

@@ -39,5 +39,5 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@EnableWebSecurity
public class WebSecurityEnablerConfiguration {
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* 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.

View File

@@ -86,7 +86,7 @@ public class OAuth2RestOperationsConfiguration {
@Configuration
@ConditionalOnBean(OAuth2ClientConfiguration.class)
@Conditional({OAuth2ClientIdCondition.class, NoClientCredentialsCondition.class})
@Conditional({ OAuth2ClientIdCondition.class, NoClientCredentialsCondition.class })
@Import(OAuth2ProtectedResourceDetailsConfiguration.class)
protected static class SessionScopedConfiguration {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* 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.

View File

@@ -55,8 +55,7 @@ class SessionRepositoryFilterConfiguration {
return null;
}
return servletProperties.getFilterDispatcherTypes().stream()
.map((type) -> DispatcherType.valueOf(type.name()))
.collect(Collectors
.map((type) -> DispatcherType.valueOf(type.name())).collect(Collectors
.collectingAndThen(Collectors.toSet(), EnumSet::copyOf));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* 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.

View File

@@ -95,8 +95,8 @@ public class FlywayAutoConfigurationTests {
@Test
public void createDataSource() throws Exception {
TestPropertyValues.of("spring.flyway.url:jdbc:hsqldb:mem:flywaytest", "spring.flyway.user:sa")
.applyTo(this.context);
TestPropertyValues.of("spring.flyway.url:jdbc:hsqldb:mem:flywaytest",
"spring.flyway.user:sa").applyTo(this.context);
registerAndRefresh(EmbeddedDataSourceConfiguration.class,
FlywayAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
@@ -162,7 +162,8 @@ public class FlywayAutoConfigurationTests {
@Test
public void changeLogDoesNotExist() throws Exception {
TestPropertyValues.of("spring.flyway.locations:file:no-such-dir").applyTo(this.context);
TestPropertyValues.of("spring.flyway.locations:file:no-such-dir")
.applyTo(this.context);
this.thrown.expect(BeanCreationException.class);
registerAndRefresh(EmbeddedDataSourceConfiguration.class,
FlywayAutoConfiguration.class,

View File

@@ -318,7 +318,8 @@ public class DataSourceAutoConfigurationTests {
@Override
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException {
for (EmbeddedDatabaseConnection candidate : EmbeddedDatabaseConnection.values()) {
for (EmbeddedDatabaseConnection candidate : EmbeddedDatabaseConnection
.values()) {
if (name.equals(candidate.getDriverClassName())) {
throw new ClassNotFoundException();
}
@@ -328,5 +329,4 @@ public class DataSourceAutoConfigurationTests {
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* 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.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* 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.

View File

@@ -160,7 +160,8 @@ public class LiquibaseAutoConfigurationTests {
@Test
public void testOverrideDefaultSchema() throws Exception {
TestPropertyValues.of("spring.liquibase.default-schema:public").applyTo(this.context);
TestPropertyValues.of("spring.liquibase.default-schema:public")
.applyTo(this.context);
this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
@@ -182,9 +183,8 @@ public class LiquibaseAutoConfigurationTests {
@Test
public void testOverrideDataSource() throws Exception {
TestPropertyValues
.of("spring.liquibase.url:jdbc:hsqldb:mem:liquibase", "spring.liquibase.user:sa")
.applyTo(this.context);
TestPropertyValues.of("spring.liquibase.url:jdbc:hsqldb:mem:liquibase",
"spring.liquibase.user:sa").applyTo(this.context);
this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
@@ -198,7 +198,8 @@ public class LiquibaseAutoConfigurationTests {
@Test(expected = BeanCreationException.class)
public void testChangeLogDoesNotExist() throws Exception {
TestPropertyValues.of("spring.liquibase.change-log:classpath:/no-such-changelog.yaml")
TestPropertyValues
.of("spring.liquibase.change-log:classpath:/no-such-changelog.yaml")
.applyTo(this.context);
this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class,
@@ -220,7 +221,8 @@ public class LiquibaseAutoConfigurationTests {
@Test
public void testOverrideLabels() throws Exception {
TestPropertyValues.of("spring.liquibase.labels:test, production").applyTo(this.context);
TestPropertyValues.of("spring.liquibase.labels:test, production")
.applyTo(this.context);
this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
@@ -232,7 +234,8 @@ public class LiquibaseAutoConfigurationTests {
@Test
@SuppressWarnings("unchecked")
public void testOverrideParameters() throws Exception {
TestPropertyValues.of("spring.liquibase.parameters.foo:bar").applyTo(this.context);
TestPropertyValues.of("spring.liquibase.parameters.foo:bar")
.applyTo(this.context);
this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);

View File

@@ -298,8 +298,8 @@ public class SecurityAutoConfigurationTests {
this.context.setServletContext(new MockServletContext());
this.context.register(SecurityAutoConfiguration.class);
this.context.refresh();
String password = this.outputCapture.toString().split("Using default security password: ")[1]
.split("\n")[0].trim();
String password = this.outputCapture.toString()
.split("Using default security password: ")[1].split("\n")[0].trim();
AuthenticationManager manager = this.context.getBean(AuthenticationManager.class);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
"user", password);
@@ -307,16 +307,17 @@ public class SecurityAutoConfigurationTests {
}
@Test
public void testCustomAuthenticationDoesNotCreateDefaultUser()
throws Exception {
public void testCustomAuthenticationDoesNotCreateDefaultUser() throws Exception {
this.context = new AnnotationConfigWebApplicationContext();
this.context.setServletContext(new MockServletContext());
this.context.register(AuthenticationManagerCustomizer.class,
SecurityAutoConfiguration.class);
this.context.refresh();
AuthenticationManager manager = this.context.getBean(AuthenticationManager.class);
assertThat(this.outputCapture.toString()).doesNotContain("Using default security password: ");
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("foo", "bar");
assertThat(this.outputCapture.toString())
.doesNotContain("Using default security password: ");
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
"foo", "bar");
assertThat(manager.authenticate(token)).isNotNull();
}

View File

@@ -61,13 +61,12 @@ public class SecurityFilterAutoConfigurationEarlyInitializationTests {
@Test
public void testSecurityFilterDoesNotCauseEarlyInitialization() throws Exception {
try (AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext()) {
TestPropertyValues.of("server.port:0")
.applyTo(context);
TestPropertyValues.of("server.port:0").applyTo(context);
context.register(Config.class);
context.refresh();
int port = context.getWebServer().getPort();
String password = this.outputCapture.toString().split("Using default security password: ")[1]
.split("\n")[0].trim();
String password = this.outputCapture.toString()
.split("Using default security password: ")[1].split("\n")[0].trim();
new TestRestTemplate("user", password)
.getForEntity("http://localhost:" + port, Object.class);
// If early initialization occurred a ConverterNotFoundException is thrown
@@ -80,8 +79,8 @@ public class SecurityFilterAutoConfigurationEarlyInitializationTests {
ConverterBean.class })
@ImportAutoConfiguration({ WebMvcAutoConfiguration.class,
JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
DispatcherServletAutoConfiguration.class,
SecurityAutoConfiguration.class, SecurityFilterAutoConfiguration.class,
DispatcherServletAutoConfiguration.class, SecurityAutoConfiguration.class,
SecurityFilterAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class })
static class Config {

View File

@@ -46,15 +46,16 @@ public class SpringBootSecurityTests {
private MockHttpServletRequest request = new MockHttpServletRequest();
private static String[] STATIC_RESOURCES = new String[]{"/css/**", "/js/**",
"/images/**", "/webjars/**", "/**/favicon.ico"};
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);
this.bootSecurity = new SpringBootSecurity(this.endpointPathResolver,
this.errorController);
}
@Test
@@ -65,7 +66,8 @@ public class SpringBootSecurityTests {
}
@Test
public void endpointIdsShouldReturnRequestMatcherWithEndpointPaths() throws Exception {
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");
@@ -77,8 +79,10 @@ public class SpringBootSecurityTests {
}
@Test
public void endpointIdsShouldReturnRequestMatcherWithAllEndpointPaths() throws Exception {
RequestMatcher requestMatcher = this.bootSecurity.endpointIds(SpringBootSecurity.ALL_ENDPOINTS);
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");
@@ -112,7 +116,8 @@ public class SpringBootSecurityTests {
}
@Test
public void staticResourcesShouldReturnRequestMatcherWithStaticResources() throws Exception {
public void staticResourcesShouldReturnRequestMatcherWithStaticResources()
throws Exception {
RequestMatcher requestMatcher = this.bootSecurity.staticResources();
assertThat(requestMatcher).isInstanceOf(OrRequestMatcher.class);
for (String resource : STATIC_RESOURCES) {
@@ -122,7 +127,8 @@ public class SpringBootSecurityTests {
}
@Test
public void errorShouldReturnRequestMatcherWithErrorControllerPath() throws Exception {
public void errorShouldReturnRequestMatcherWithErrorControllerPath()
throws Exception {
RequestMatcher requestMatcher = this.bootSecurity.error();
assertThat(requestMatcher).isInstanceOf(AntPathRequestMatcher.class);
this.request.setServletPath("/test/error");
@@ -152,6 +158,7 @@ public class SpringBootSecurityTests {
public String getErrorPath() {
return "/test/error";
}
}
@Endpoint(id = "id-1")
@@ -167,4 +174,5 @@ public class SpringBootSecurityTests {
static class FakeEndpoint {
}
}

View File

@@ -22,6 +22,7 @@ import org.junit.rules.ExpectedException;
import org.mockito.Mockito;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.autoconfigure.web.servlet.MockServletWebServerFactory;
import org.springframework.boot.builder.SpringApplicationBuilder;
@@ -77,8 +78,7 @@ public class OAuth2RestOperationsConfigurationTests {
TestPropertyValues.of("security.oauth2.client.client-id=acme")
.applyTo(this.environment);
initializeContext(ConfigForRequestScopedConfiguration.class, false);
assertThat(this.context.containsBean("oauth2ClientContext"))
.isTrue();
assertThat(this.context.containsBean("oauth2ClientContext")).isTrue();
}
@Test
@@ -93,8 +93,7 @@ public class OAuth2RestOperationsConfigurationTests {
TestPropertyValues.of("security.oauth2.client.client-id=acme")
.applyTo(this.environment);
initializeContext(ConfigForSessionScopedConfiguration.class, false);
assertThat(this.context.containsBean("oauth2ClientContext"))
.isTrue();
assertThat(this.context.containsBean("oauth2ClientContext")).isTrue();
}
@Test
@@ -104,10 +103,11 @@ public class OAuth2RestOperationsConfigurationTests {
this.context.getBean(DefaultOAuth2ClientContext.class);
}
private void initializeContext(Class<?> configuration, boolean isClientCredentials) {
private void initializeContext(Class<?> configuration, boolean clientCredentials) {
this.context = new SpringApplicationBuilder(configuration)
.environment(this.environment)
.web(!isClientCredentials).run();
.environment(this.environment).web(clientCredentials
? WebApplicationType.NONE : WebApplicationType.SERVLET)
.run();
}
@Configuration
@@ -123,7 +123,8 @@ public class OAuth2RestOperationsConfigurationTests {
@Configuration
@Import({ OAuth2ClientConfiguration.class, OAuth2RestOperationsConfiguration.class })
protected static class ConfigForSessionScopedConfiguration extends WebApplicationConfiguration {
protected static class ConfigForSessionScopedConfiguration
extends WebApplicationConfiguration {
@Bean
public SecurityProperties securityProperties() {
@@ -133,7 +134,8 @@ public class OAuth2RestOperationsConfigurationTests {
}
@Configuration
protected static class ConfigForRequestScopedConfiguration extends WebApplicationConfiguration {
protected static class ConfigForRequestScopedConfiguration
extends WebApplicationConfiguration {
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* 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.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* 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.