Switch off CSRF filter

Might need to revisit later.
This commit is contained in:
Dave Syer 2013-08-22 14:19:26 +01:00 committed by Phillip Webb
parent 43fc107437
commit 1e0e2e7102
10 changed files with 195 additions and 132 deletions

View File

@ -17,7 +17,10 @@
package org.springframework.boot.actuate.autoconfigure;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@ -25,8 +28,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping;
import org.springframework.boot.actuate.properties.ManagementServerProperties;
import org.springframework.boot.actuate.properties.ManagementServerProperties.User;
import org.springframework.boot.actuate.properties.SecurityProperties;
import org.springframework.boot.actuate.properties.SecurityProperties.User;
import org.springframework.boot.actuate.web.ErrorController;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@ -40,13 +43,14 @@ import org.springframework.security.authentication.AuthenticationEventPublisher;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity.IgnoredRequestConfigurer;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
@ -85,6 +89,7 @@ import org.springframework.security.web.authentication.www.BasicAuthenticationEn
@Configuration
@ConditionalOnClass({ EnableWebSecurity.class })
@EnableWebSecurity
// (debug = true)
@EnableConfigurationProperties
public class SecurityAutoConfiguration {
@ -101,27 +106,25 @@ public class SecurityAutoConfiguration {
}
@Bean
@ConditionalOnMissingBean({ BoostrapWebSecurityConfigurerAdapter.class })
public WebSecurityConfigurerAdapter webSecurityConfigurerAdapter() {
return new BoostrapWebSecurityConfigurerAdapter();
@ConditionalOnMissingBean({ ApplicationWebSecurityConfigurerAdapter.class })
public WebSecurityConfigurerAdapter applicationWebSecurityConfigurerAdapter() {
return new ApplicationWebSecurityConfigurerAdapter();
}
@Bean
@ConditionalOnMissingBean({ ManagementWebSecurityConfigurerAdapter.class })
public WebSecurityConfigurerAdapter managementWebSecurityConfigurerAdapter() {
return new ManagementWebSecurityConfigurerAdapter();
}
// Give user-supplied filters a chance to be last in line
@Order(Ordered.LOWEST_PRECEDENCE - 10)
private static class BoostrapWebSecurityConfigurerAdapter extends
@Order(Ordered.LOWEST_PRECEDENCE - 5)
private static class ApplicationWebSecurityConfigurerAdapter extends
WebSecurityConfigurerAdapter {
private static final String[] NO_PATHS = new String[0];
@Autowired
private SecurityProperties security;
@Autowired
private ManagementServerProperties management;
@Autowired(required = false)
private EndpointHandlerMapping endpointHandlerMapping;
@Autowired
private AuthenticationEventPublisher authenticationEventPublisher;
@ -135,26 +138,20 @@ public class SecurityAutoConfiguration {
http.requiresChannel().anyRequest().requiresSecure();
}
if (this.security.getBasic().isEnabled()) {
String[] paths = getSecureApplicationPaths();
if (this.security.getBasic().isEnabled() && paths.length > 0) {
http.exceptionHandling().authenticationEntryPoint(entryPoint());
http.httpBasic().and().anonymous().disable();
ExpressionUrlAuthorizationConfigurer<HttpSecurity> authorizeUrls = http
.authorizeUrls();
String[] paths = getEndpointPaths(true);
if (paths.length > 0) {
authorizeUrls.antMatchers(getEndpointPaths(true)).hasRole(
this.management.getUser().getRole());
}
paths = getSecureApplicationPaths();
if (paths.length > 0) {
authorizeUrls.antMatchers(getSecureApplicationPaths()).hasRole(
this.security.getBasic().getRole());
}
authorizeUrls.and().httpBasic();
http.requestMatchers().antMatchers(paths);
http.authorizeRequests().anyRequest()
.hasRole(this.security.getUser().getRole()) //
.and().httpBasic() //
.and().anonymous().disable();
}
// No cookies for service endpoints by default
// Remove this when session creation is disabled by default
http.csrf().disable();
// No cookies for application endpoints by default
http.sessionManagement().sessionCreationPolicy(this.security.getSessions());
}
private String[] getSecureApplicationPaths() {
@ -181,12 +178,74 @@ public class SecurityAutoConfiguration {
public void configure(WebSecurity builder) throws Exception {
IgnoredRequestConfigurer ignoring = builder.ignoring();
ignoring.antMatchers(this.security.getIgnored());
ignoring.antMatchers(getEndpointPaths(false));
if (this.errorController != null) {
ignoring.antMatchers(this.errorController.getErrorPath());
}
}
@Override
protected AuthenticationManager authenticationManager() throws Exception {
AuthenticationManager manager = super.authenticationManager();
if (manager instanceof ProviderManager) {
((ProviderManager) manager)
.setAuthenticationEventPublisher(this.authenticationEventPublisher);
}
return manager;
}
}
// Give user-supplied filters a chance to be last in line
@Order(Ordered.LOWEST_PRECEDENCE - 10)
private static class ManagementWebSecurityConfigurerAdapter extends
WebSecurityConfigurerAdapter {
private static final String[] NO_PATHS = new String[0];
@Autowired
private SecurityProperties security;
@Autowired
private ManagementServerProperties management;
@Autowired(required = false)
private EndpointHandlerMapping endpointHandlerMapping;
@Override
protected void configure(HttpSecurity http) throws Exception {
if (this.security.isRequireSsl()) {
http.requiresChannel().anyRequest().requiresSecure();
}
String[] paths = getEndpointPaths(true);
if (this.security.getBasic().isEnabled() && paths.length > 0) {
http.exceptionHandling().authenticationEntryPoint(entryPoint());
http.requestMatchers().antMatchers(paths);
http.authorizeRequests().anyRequest()
.hasRole(this.security.getManagement().getRole()) //
.and().httpBasic() //
.and().anonymous().disable();
}
// No cookies for management endpoints by default
http.csrf().disable();
http.sessionManagement().sessionCreationPolicy(
this.security.getManagement().getSessions());
}
@Override
public void configure(WebSecurity builder) throws Exception {
IgnoredRequestConfigurer ignoring = builder.ignoring();
ignoring.antMatchers(getEndpointPaths(false));
}
private AuthenticationEntryPoint entryPoint() {
BasicAuthenticationEntryPoint entryPoint = new BasicAuthenticationEntryPoint();
entryPoint.setRealmName(this.security.getBasic().getRealm());
return entryPoint;
}
private String[] getEndpointPaths(boolean secure) {
if (this.endpointHandlerMapping == null) {
return NO_PATHS;
@ -202,16 +261,6 @@ public class SecurityAutoConfiguration {
return paths.toArray(new String[paths.size()]);
}
@Override
protected AuthenticationManager authenticationManager() throws Exception {
AuthenticationManager manager = super.authenticationManager();
if (manager instanceof ProviderManager) {
((ProviderManager) manager)
.setAuthenticationEventPublisher(this.authenticationEventPublisher);
}
return manager;
}
}
@ConditionalOnMissingBean(AuthenticationManager.class)
@ -222,23 +271,28 @@ public class SecurityAutoConfiguration {
.getLog(AuthenticationManagerConfiguration.class);
@Autowired
private ManagementServerProperties management;
private SecurityProperties security;
@Bean
public AuthenticationManager authenticationManager() throws Exception {
User user = this.management.getUser();
InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> builder = new AuthenticationManagerBuilder(
ObjectPostProcessor.QUIESCENT_POSTPROCESSOR).inMemoryAuthentication();
User user = this.security.getUser();
if (user.isDefaultPassword()) {
logger.info("Using default password for management endpoints: "
logger.info("Using default password for application endpoints: "
+ user.getPassword());
}
List<String> roles = new ArrayList<String>();
roles.add("USER");
if (!"USER".equals(user.getRole())) {
roles.add(user.getRole());
}
return new AuthenticationManagerBuilder().inMemoryAuthentication()
.withUser(user.getName()).password(user.getPassword())
.roles(roles.toArray(new String[roles.size()])).and().and().build();
Set<String> roles = new LinkedHashSet<String>(Arrays.asList(this.security
.getManagement().getRole(), user.getRole()));
builder.withUser(user.getName()).password(user.getPassword())
.roles(roles.toArray(new String[roles.size()]));
return builder.and().build();
}
}

View File

@ -17,7 +17,6 @@
package org.springframework.boot.actuate.properties;
import java.net.InetAddress;
import java.util.UUID;
import javax.validation.constraints.NotNull;
@ -40,14 +39,8 @@ public class ManagementServerProperties {
@NotNull
private String contextPath = "";
private User user = new User();
private boolean allowShutdown = false;
public User getUser() {
return this.user;
}
public boolean isAllowShutdown() {
return this.allowShutdown;
}
@ -89,45 +82,4 @@ public class ManagementServerProperties {
this.contextPath = contextPath;
}
public static class User {
private String name = "user";
private String password = UUID.randomUUID().toString();
private String role = "ADMIN";
private boolean defaultPassword;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.defaultPassword = false;
this.password = password;
}
public String getRole() {
return this.role;
}
public void setRole(String role) {
this.role = role;
}
public boolean isDefaultPassword() {
return this.defaultPassword;
}
}
}

View File

@ -16,8 +16,10 @@
package org.springframework.boot.actuate.properties;
import java.util.UUID;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.security.config.annotation.web.configurers.SessionCreationPolicy;
import org.springframework.security.config.http.SessionCreationPolicy;
/**
* Properties for the security aspects of an application.
@ -31,11 +33,23 @@ public class SecurityProperties {
private Basic basic = new Basic();
private SessionCreationPolicy sessions = SessionCreationPolicy.stateless;
private SessionCreationPolicy sessions = SessionCreationPolicy.STATELESS;
private String[] ignored = new String[] { "/css/**", "/js/**", "/images/**",
"/**/favicon.ico" };
private Management management = new Management();
private User user = new User();
public User getUser() {
return this.user;
}
public Management getManagement() {
return this.management;
}
public SessionCreationPolicy getSessions() {
return this.sessions;
}
@ -76,8 +90,6 @@ public class SecurityProperties {
private String[] path = new String[] { "/**" };
private String role = "USER";
public boolean isEnabled() {
return this.enabled;
}
@ -102,6 +114,59 @@ public class SecurityProperties {
this.path = paths;
}
}
public static class Management {
private String role = "ADMIN";
private SessionCreationPolicy sessions = SessionCreationPolicy.STATELESS;
public SessionCreationPolicy getSessions() {
return this.sessions;
}
public void setSessions(SessionCreationPolicy sessions) {
this.sessions = sessions;
}
public void setRole(String role) {
this.role = role;
}
public String getRole() {
return this.role;
}
}
public static class User {
private String name = "user";
private String password = UUID.randomUUID().toString();
private String role = "USER";
private boolean defaultPassword;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.defaultPassword = false;
this.password = password;
}
public String getRole() {
return this.role;
}
@ -110,6 +175,10 @@ public class SecurityProperties {
this.role = role;
}
public boolean isDefaultPassword() {
return this.defaultPassword;
}
}
}

View File

@ -8,7 +8,7 @@
<packaging>pom</packaging>
<properties>
<spring.version>4.0.0.BUILD-SNAPSHOT</spring.version>
<spring.security.version>3.2.0.M2</spring.security.version>
<spring.security.version>3.2.0.RC1</spring.security.version>
<spring.integration.version>2.2.4.RELEASE</spring.integration.version>
<spring.batch.version>2.2.0.RELEASE</spring.batch.version>
<groovy.version>2.1.6</groovy.version>

View File

@ -1,19 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="CONSOLE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %5p ${PID:- } [%t] --- %-40.40logger{39} : %m%n%wex"/>
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE" />
</root>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<!-- logger name="org.springframework" level="DEBUG"/ -->
</configuration>

View File

@ -30,7 +30,7 @@ import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.properties.ManagementServerProperties;
import org.springframework.boot.actuate.properties.SecurityProperties;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
@ -127,7 +127,7 @@ public class ManagementAddressSampleActuatorApplicationTests {
}
private String getPassword() {
return context.getBean(ManagementServerProperties.class).getUser().getPassword();
return context.getBean(SecurityProperties.class).getUser().getPassword();
}
private RestTemplate getRestTemplate() {

View File

@ -29,7 +29,7 @@ import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.properties.ManagementServerProperties;
import org.springframework.boot.actuate.properties.SecurityProperties;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
@ -100,7 +100,7 @@ public class NoManagementSampleActuatorApplicationTests {
}
private String getPassword() {
return context.getBean(ManagementServerProperties.class).getUser().getPassword();
return context.getBean(SecurityProperties.class).getUser().getPassword();
}
private RestTemplate getRestTemplate(final String username, final String password) {

View File

@ -29,7 +29,7 @@ import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.properties.ManagementServerProperties;
import org.springframework.boot.actuate.properties.SecurityProperties;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
@ -86,7 +86,8 @@ public class SampleActuatorApplicationTests {
@SuppressWarnings("unchecked")
Map<String, Object> body = entity.getBody();
assertEquals("Wrong body: " + body, "Unauthorized", body.get("error"));
assertFalse(entity.getHeaders().containsKey("Set-Cookie"));
assertFalse("Wrong headers: " + entity.getHeaders(), entity.getHeaders()
.containsKey("Set-Cookie"));
}
@Test
@ -168,7 +169,7 @@ public class SampleActuatorApplicationTests {
}
private String getPassword() {
return context.getBean(ManagementServerProperties.class).getUser().getPassword();
return context.getBean(SecurityProperties.class).getUser().getPassword();
}
private RestTemplate getRestTemplate() {

View File

@ -29,7 +29,7 @@ import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.properties.ManagementServerProperties;
import org.springframework.boot.actuate.properties.SecurityProperties;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
@ -100,7 +100,7 @@ public class ShutdownSampleActuatorApplicationTests {
}
private String getPassword() {
return context.getBean(ManagementServerProperties.class).getUser().getPassword();
return context.getBean(SecurityProperties.class).getUser().getPassword();
}
private RestTemplate getRestTemplate(final String username, final String password) {

View File

@ -78,7 +78,8 @@ public class UnsecureSampleActuatorApplicationTests {
@SuppressWarnings("unchecked")
Map<String, Object> body = entity.getBody();
assertEquals("Hello Phil", body.get("message"));
assertFalse(entity.getHeaders().containsKey("Set-Cookie"));
assertFalse("Wrong headers: " + entity.getHeaders(), entity.getHeaders()
.containsKey("Set-Cookie"));
}
private RestTemplate getRestTemplate() {