mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-09-03 04:26:12 +08:00
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.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.security.SecurityProperties.User;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
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.authentication.builders.AuthenticationManagerBuilder;
|
||||
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 Rob Winch
|
||||
@ -53,8 +60,15 @@ import org.springframework.security.config.annotation.authentication.configurers
|
||||
@ConditionalOnMissingBean(AuthenticationManager.class)
|
||||
@Order(Ordered.LOWEST_PRECEDENCE - 3)
|
||||
public class AuthenticationManagerConfiguration extends
|
||||
GlobalAuthenticationConfigurerAdapter implements
|
||||
ApplicationListener<ContextRefreshedEvent> {
|
||||
GlobalAuthenticationConfigurerAdapter {
|
||||
|
||||
/*
|
||||
* 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
|
||||
.getLog(AuthenticationManagerConfiguration.class);
|
||||
@ -62,43 +76,48 @@ public class AuthenticationManagerConfiguration extends
|
||||
@Autowired
|
||||
private List<SecurityPrequisite> dependencies;
|
||||
|
||||
@Autowired
|
||||
private ObjectPostProcessor<Object> objectPostProcessor;
|
||||
|
||||
@Autowired
|
||||
private SecurityProperties security;
|
||||
|
||||
@Autowired
|
||||
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);
|
||||
}
|
||||
private ObjectPostProcessor<Object> objectPostProcessor;
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public AuthenticationManager authenticationManager() {
|
||||
AuthenticationManager manager = this.configurer.getAuthenticationManagerBuilder()
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
AuthenticationManager manager = this.configurer.getAuthenticationManagerBuilder()
|
||||
.getOrBuild();
|
||||
if (manager instanceof ProviderManager) {
|
||||
((ProviderManager) manager)
|
||||
.setAuthenticationEventPublisher(this.authenticationEventPublisher);
|
||||
@Component
|
||||
protected static class AuthenticationManagerConfigurationListener implements
|
||||
ApplicationListener<ContextRefreshedEvent> {
|
||||
|
||||
@Autowired
|
||||
private AuthenticationEventPublisher authenticationEventPublisher;
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
ApplicationContext context = event.getApplicationContext();
|
||||
if (context.getBeanNamesForType(AuthenticationManager.class).length == 0) {
|
||||
return;
|
||||
}
|
||||
AuthenticationManager manager = context.getBean(AuthenticationManager.class);
|
||||
if (manager instanceof ProviderManager) {
|
||||
((ProviderManager) manager)
|
||||
.setAuthenticationEventPublisher(this.authenticationEventPublisher);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -163,7 +182,8 @@ public class AuthenticationManagerConfiguration extends
|
||||
.roles(roles.toArray(new String[roles.size()])).and().and().build();
|
||||
|
||||
// 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 javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
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.SpringApplicationConfiguration;
|
||||
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.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
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.endsWith;
|
||||
@ -40,8 +54,9 @@ import static org.junit.Assert.assertThat;
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = BasicErrorControllerMockMvcTests.TestConfiguration.class)
|
||||
@SpringApplicationConfiguration(classes = TestConfiguration.class)
|
||||
@WebAppConfiguration
|
||||
@DirtiesContext
|
||||
@IntegrationTest("server.port=0")
|
||||
public class BasicErrorControllerIntegrationTest {
|
||||
|
||||
@ -69,4 +84,49 @@ public class BasicErrorControllerIntegrationTest {
|
||||
assertThat(resp, containsString("errors=[{codes="));
|
||||
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>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
|
@ -19,18 +19,14 @@ package sample.ui.secure;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
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.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.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@ -65,16 +61,7 @@ public class SampleWebSecureApplication extends WebMvcConfigurerAdapter {
|
||||
registry.addViewController("/login").setViewName("login");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ApplicationSecurity applicationSecurity() {
|
||||
return new ApplicationSecurity();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationSecurity authenticationSecurity() {
|
||||
return new AuthenticationSecurity();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
|
||||
protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@ -86,21 +73,14 @@ public class SampleWebSecureApplication extends WebMvcConfigurerAdapter {
|
||||
http.authorizeRequests().anyRequest().fullyAuthenticated().and().formLogin()
|
||||
.loginPage("/login").failureUrl("/login?error").permitAll();
|
||||
}
|
||||
}
|
||||
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE + 10)
|
||||
protected static class AuthenticationSecurity extends
|
||||
GlobalAuthenticationConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
private DataSource dataSource;
|
||||
|
||||
@Override
|
||||
public void init(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.jdbcAuthentication().dataSource(this.dataSource).withUser("admin")
|
||||
.password("admin").roles("ADMIN", "USER").and().withUser("user")
|
||||
.password("user").roles("USER");
|
||||
public void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.inMemoryAuthentication().withUser("admin").password("admin")
|
||||
.roles("ADMIN", "USER").and().withUser("user").password("user")
|
||||
.roles("USER");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user