Merge branch '1.1.x'
This commit is contained in:
commit
389c4f3e0b
|
|
@ -26,6 +26,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.security.SecurityProperties.User;
|
import org.springframework.boot.autoconfigure.security.SecurityProperties.User;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationListener;
|
import org.springframework.context.ApplicationListener;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
@ -41,9 +42,15 @@ import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||||
import org.springframework.security.config.annotation.SecurityConfigurer;
|
import org.springframework.security.config.annotation.SecurityConfigurer;
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
|
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration for a Spring Security in-memory {@link AuthenticationManager}.
|
* Configuration for a Spring Security in-memory {@link AuthenticationManager}. Can be
|
||||||
|
* disabled by providing a bean of type AuthenticationManager. 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 Dave Syer
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
|
|
@ -53,8 +60,15 @@ import org.springframework.security.config.annotation.authentication.configurers
|
||||||
@ConditionalOnMissingBean(AuthenticationManager.class)
|
@ConditionalOnMissingBean(AuthenticationManager.class)
|
||||||
@Order(Ordered.LOWEST_PRECEDENCE - 3)
|
@Order(Ordered.LOWEST_PRECEDENCE - 3)
|
||||||
public class AuthenticationManagerConfiguration extends
|
public class AuthenticationManagerConfiguration extends
|
||||||
GlobalAuthenticationConfigurerAdapter implements
|
GlobalAuthenticationConfigurerAdapter {
|
||||||
ApplicationListener<ContextRefreshedEvent> {
|
|
||||||
|
/*
|
||||||
|
* Yes, this class is a GlobalAuthenticationConfigurerAdapter, even though none of
|
||||||
|
* those methods are overridden: we want Spring Security to instantiate us early, so
|
||||||
|
* we can in turn force the SecurityPrequisites to be instantiated. This will prevent
|
||||||
|
* ordering issues between Spring Boot modules when they need to influence the default
|
||||||
|
* security configuration.
|
||||||
|
*/
|
||||||
|
|
||||||
private static Log logger = LogFactory
|
private static Log logger = LogFactory
|
||||||
.getLog(AuthenticationManagerConfiguration.class);
|
.getLog(AuthenticationManagerConfiguration.class);
|
||||||
|
|
@ -63,44 +77,49 @@ public class AuthenticationManagerConfiguration extends
|
||||||
private List<SecurityPrequisite> dependencies;
|
private List<SecurityPrequisite> dependencies;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ObjectPostProcessor<Object> objectPostProcessor;
|
private SecurityProperties security;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SecurityProperties security;
|
private ObjectPostProcessor<Object> objectPostProcessor;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Primary
|
||||||
|
public AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth)
|
||||||
|
throws Exception {
|
||||||
|
/*
|
||||||
|
* This AuthenticationManagerBuilder is for the global AuthenticationManager
|
||||||
|
*/
|
||||||
|
BootDefaultingAuthenticationConfigurerAdapter configurer = new BootDefaultingAuthenticationConfigurerAdapter();
|
||||||
|
configurer.init(auth);
|
||||||
|
configurer.configure(auth);
|
||||||
|
AuthenticationManager manager = configurer.getAuthenticationManagerBuilder()
|
||||||
|
.getOrBuild();
|
||||||
|
configurer.configureParent(auth);
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component
|
||||||
|
protected static class AuthenticationManagerConfigurationListener implements
|
||||||
|
ApplicationListener<ContextRefreshedEvent> {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AuthenticationEventPublisher authenticationEventPublisher;
|
private AuthenticationEventPublisher authenticationEventPublisher;
|
||||||
|
|
||||||
private BootDefaultingAuthenticationConfigurerAdapter configurer = new BootDefaultingAuthenticationConfigurerAdapter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(AuthenticationManagerBuilder auth) throws Exception {
|
|
||||||
auth.apply(this.configurer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void configure(AuthenticationManagerBuilder auth) throws Exception {
|
|
||||||
this.configurer.configureParent(auth);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@Primary
|
|
||||||
public AuthenticationManager authenticationManager() {
|
|
||||||
AuthenticationManager manager = this.configurer.getAuthenticationManagerBuilder()
|
|
||||||
.getOrBuild();
|
|
||||||
return manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||||
AuthenticationManager manager = this.configurer.getAuthenticationManagerBuilder()
|
ApplicationContext context = event.getApplicationContext();
|
||||||
.getOrBuild();
|
if (context.getBeanNamesForType(AuthenticationManager.class).length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
AuthenticationManager manager = context.getBean(AuthenticationManager.class);
|
||||||
if (manager instanceof ProviderManager) {
|
if (manager instanceof ProviderManager) {
|
||||||
((ProviderManager) manager)
|
((ProviderManager) manager)
|
||||||
.setAuthenticationEventPublisher(this.authenticationEventPublisher);
|
.setAuthenticationEventPublisher(this.authenticationEventPublisher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We must add {@link BootDefaultingAuthenticationConfigurerAdapter} in the init phase
|
* We must add {@link BootDefaultingAuthenticationConfigurerAdapter} in the init phase
|
||||||
* of the last {@link GlobalAuthenticationConfigurerAdapter}. The reason is that the
|
* of the last {@link GlobalAuthenticationConfigurerAdapter}. The reason is that the
|
||||||
|
|
@ -163,7 +182,8 @@ public class AuthenticationManagerConfiguration extends
|
||||||
.roles(roles.toArray(new String[roles.size()])).and().and().build();
|
.roles(roles.toArray(new String[roles.size()])).and().and().build();
|
||||||
|
|
||||||
// Defer actually setting the parent on the AuthenticationManagerBuilder
|
// Defer actually setting the parent on the AuthenticationManagerBuilder
|
||||||
// because it makes it "configured" and we are only in the init() phase here.
|
// because it makes it "configured" and we are only in the init() phase
|
||||||
|
// here.
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,29 @@ package org.springframework.boot.autoconfigure.web;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.web.BasicErrorControllerMockMvcTests.MinimalWebConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.web.BasicErrorControllerMockMvcTests.TestConfiguration;
|
||||||
import org.springframework.boot.test.IntegrationTest;
|
import org.springframework.boot.test.IntegrationTest;
|
||||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||||
import org.springframework.boot.test.TestRestTemplate;
|
import org.springframework.boot.test.TestRestTemplate;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
import org.springframework.test.context.web.WebAppConfiguration;
|
import org.springframework.test.context.web.WebAppConfiguration;
|
||||||
|
import org.springframework.validation.BindException;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.servlet.View;
|
||||||
|
import org.springframework.web.servlet.view.AbstractView;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.hamcrest.Matchers.endsWith;
|
import static org.hamcrest.Matchers.endsWith;
|
||||||
|
|
@ -40,8 +54,9 @@ import static org.junit.Assert.assertThat;
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
*/
|
*/
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@SpringApplicationConfiguration(classes = BasicErrorControllerMockMvcTests.TestConfiguration.class)
|
@SpringApplicationConfiguration(classes = TestConfiguration.class)
|
||||||
@WebAppConfiguration
|
@WebAppConfiguration
|
||||||
|
@DirtiesContext
|
||||||
@IntegrationTest("server.port=0")
|
@IntegrationTest("server.port=0")
|
||||||
public class BasicErrorControllerIntegrationTest {
|
public class BasicErrorControllerIntegrationTest {
|
||||||
|
|
||||||
|
|
@ -69,4 +84,49 @@ public class BasicErrorControllerIntegrationTest {
|
||||||
assertThat(resp, containsString("errors=[{codes="));
|
assertThat(resp, containsString("errors=[{codes="));
|
||||||
assertThat(resp, containsString("org.springframework.validation.BindException"));
|
assertThat(resp, containsString("org.springframework.validation.BindException"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@MinimalWebConfiguration
|
||||||
|
public static class TestConfiguration {
|
||||||
|
|
||||||
|
// For manual testing
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(TestConfiguration.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public View error() {
|
||||||
|
return new AbstractView() {
|
||||||
|
@Override
|
||||||
|
protected void renderMergedOutputModel(Map<String, Object> model,
|
||||||
|
HttpServletRequest request, HttpServletResponse response)
|
||||||
|
throws Exception {
|
||||||
|
response.getWriter().write("ERROR_BEAN");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
protected static class Errors {
|
||||||
|
|
||||||
|
public String getFoo() {
|
||||||
|
return "foo";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/")
|
||||||
|
public String home() {
|
||||||
|
throw new IllegalStateException("Expected!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/bind")
|
||||||
|
public String bind() throws Exception {
|
||||||
|
BindException error = new BindException(this, "test");
|
||||||
|
error.rejectValue("foo", "bar.error");
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,18 +23,10 @@
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-security</artifactId>
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.h2database</groupId>
|
|
||||||
<artifactId>h2</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.httpcomponents</groupId>
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
<artifactId>httpclient</artifactId>
|
<artifactId>httpclient</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -19,18 +19,14 @@ package sample.ui.secure;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
|
|
@ -65,16 +61,7 @@ public class SampleWebSecureApplication extends WebMvcConfigurerAdapter {
|
||||||
registry.addViewController("/login").setViewName("login");
|
registry.addViewController("/login").setViewName("login");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Configuration
|
||||||
public ApplicationSecurity applicationSecurity() {
|
|
||||||
return new ApplicationSecurity();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public AuthenticationSecurity authenticationSecurity() {
|
|
||||||
return new AuthenticationSecurity();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
|
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
|
||||||
protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter {
|
protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
|
|
@ -86,21 +73,14 @@ public class SampleWebSecureApplication extends WebMvcConfigurerAdapter {
|
||||||
http.authorizeRequests().anyRequest().fullyAuthenticated().and().formLogin()
|
http.authorizeRequests().anyRequest().fullyAuthenticated().and().formLogin()
|
||||||
.loginPage("/login").failureUrl("/login?error").permitAll();
|
.loginPage("/login").failureUrl("/login?error").permitAll();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Order(Ordered.HIGHEST_PRECEDENCE + 10)
|
|
||||||
protected static class AuthenticationSecurity extends
|
|
||||||
GlobalAuthenticationConfigurerAdapter {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private DataSource dataSource;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(AuthenticationManagerBuilder auth) throws Exception {
|
public void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||||
auth.jdbcAuthentication().dataSource(this.dataSource).withUser("admin")
|
auth.inMemoryAuthentication().withUser("admin").password("admin")
|
||||||
.password("admin").roles("ADMIN", "USER").and().withUser("user")
|
.roles("ADMIN", "USER").and().withUser("user").password("user")
|
||||||
.password("user").roles("USER");
|
.roles("USER");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue