diff --git a/spring-security-rest/pom.xml b/spring-security-rest/pom.xml index af69b57de1..265da0bbcd 100644 --- a/spring-security-rest/pom.xml +++ b/spring-security-rest/pom.xml @@ -153,6 +153,13 @@ test + + org.springframework.security + spring-security-test + ${org.springframework.security.version} + + + com.jayway.restassured rest-assured diff --git a/spring-security-rest/src/main/java/org/baeldung/spring/SecurityJavaConfig.java b/spring-security-rest/src/main/java/org/baeldung/spring/SecurityJavaConfig.java index 5b88fefdb2..60866fd2eb 100644 --- a/spring-security-rest/src/main/java/org/baeldung/spring/SecurityJavaConfig.java +++ b/spring-security-rest/src/main/java/org/baeldung/spring/SecurityJavaConfig.java @@ -42,7 +42,7 @@ public class SecurityJavaConfig extends WebSecurityConfigurerAdapter { .authenticationEntryPoint(restAuthenticationEntryPoint) .and() .authorizeRequests() - .antMatchers("/api/**").authenticated() + .antMatchers("/**").authenticated() .and() .formLogin() .successHandler(authenticationSuccessHandler) diff --git a/spring-security-rest/src/main/java/org/baeldung/spring/SecurityWithCsrfConfig.java b/spring-security-rest/src/main/java/org/baeldung/spring/SecurityWithCsrfConfig.java new file mode 100644 index 0000000000..c372a7ca90 --- /dev/null +++ b/spring-security-rest/src/main/java/org/baeldung/spring/SecurityWithCsrfConfig.java @@ -0,0 +1,63 @@ +package org.baeldung.spring; + +import org.baeldung.security.MySavedRequestAwareAuthenticationSuccessHandler; +import org.baeldung.security.RestAuthenticationEntryPoint; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; + +@Configuration +@EnableWebSecurity +@ComponentScan("org.baeldung.security") +public class SecurityWithCsrfConfig extends WebSecurityConfigurerAdapter { + + @Autowired + private RestAuthenticationEntryPoint restAuthenticationEntryPoint; + + @Autowired + private MySavedRequestAwareAuthenticationSuccessHandler authenticationSuccessHandler; + + public SecurityWithCsrfConfig() { + super(); + } + + // + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication().withUser("temporary").password("temporary").roles("ADMIN").and().withUser("user").password("userPass").roles("USER"); + } + + @Override + protected void configure(final HttpSecurity http) throws Exception {// @formatter:off + http + .exceptionHandling() + .authenticationEntryPoint(restAuthenticationEntryPoint) + .and() + .authorizeRequests() + .antMatchers("/**").authenticated() + .and() + .formLogin() + .successHandler(authenticationSuccessHandler) + .failureHandler(new SimpleUrlAuthenticationFailureHandler()) + .and() + .logout(); + } // @formatter:on + + @Bean + public MySavedRequestAwareAuthenticationSuccessHandler mySuccessHandler() { + return new MySavedRequestAwareAuthenticationSuccessHandler(); + } + + @Bean + public SimpleUrlAuthenticationFailureHandler myFailureHandler() { + return new SimpleUrlAuthenticationFailureHandler(); + } + +} \ No newline at end of file diff --git a/spring-security-rest/src/test/java/org/baeldung/csrf/CsrfAbstractIntegrationTest.java b/spring-security-rest/src/test/java/org/baeldung/csrf/CsrfAbstractIntegrationTest.java new file mode 100644 index 0000000000..19ba8fdd3c --- /dev/null +++ b/spring-security-rest/src/test/java/org/baeldung/csrf/CsrfAbstractIntegrationTest.java @@ -0,0 +1,45 @@ +package org.baeldung.csrf; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; + +import javax.servlet.Filter; + +import org.baeldung.persistence.model.Foo; +import org.junit.Before; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.RequestPostProcessor; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +public class CsrfAbstractIntegrationTest { + @Autowired + private WebApplicationContext context; + + @Autowired + private Filter springSecurityFilterChain; + + protected MockMvc mvc; + + @Before + public void setup() { + mvc = MockMvcBuilders.webAppContextSetup(context).addFilters(springSecurityFilterChain).build(); + } + + protected RequestPostProcessor testUser() { + return user("user").password("userPass").roles("USER"); + } + + protected String createFoo() throws JsonProcessingException { + return new ObjectMapper().writeValueAsString(new Foo(randomAlphabetic(6))); + } +} diff --git a/spring-security-rest/src/test/java/org/baeldung/csrf/CsrfDisabledIntegrationTest.java b/spring-security-rest/src/test/java/org/baeldung/csrf/CsrfDisabledIntegrationTest.java new file mode 100644 index 0000000000..6705c53ae9 --- /dev/null +++ b/spring-security-rest/src/test/java/org/baeldung/csrf/CsrfDisabledIntegrationTest.java @@ -0,0 +1,27 @@ +package org.baeldung.csrf; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.baeldung.spring.ClientWebConfig; +import org.baeldung.spring.SecurityJavaConfig; +import org.baeldung.spring.SwaggerConfig; +import org.baeldung.spring.WebConfig; +import org.junit.Test; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; + +@ContextConfiguration(classes = { SecurityJavaConfig.class, ClientWebConfig.class, WebConfig.class, SwaggerConfig.class }) +public class CsrfDisabledIntegrationTest extends CsrfAbstractIntegrationTest { + + @Test + public void givenNotAuth_whenAddFoo_thenUnauthorized() throws Exception { + mvc.perform(post("/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo())).andExpect(status().isUnauthorized()); + } + + @Test + public void givenAuth_whenAddFoo_thenCreated() throws Exception { + mvc.perform(post("/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo()).with(testUser())).andExpect(status().isCreated()); + } + +} diff --git a/spring-security-rest/src/test/java/org/baeldung/csrf/CsrfEnabledIntegrationTest.java b/spring-security-rest/src/test/java/org/baeldung/csrf/CsrfEnabledIntegrationTest.java new file mode 100644 index 0000000000..721e9e7c52 --- /dev/null +++ b/spring-security-rest/src/test/java/org/baeldung/csrf/CsrfEnabledIntegrationTest.java @@ -0,0 +1,28 @@ +package org.baeldung.csrf; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.baeldung.spring.ClientWebConfig; +import org.baeldung.spring.SecurityWithCsrfConfig; +import org.baeldung.spring.SwaggerConfig; +import org.baeldung.spring.WebConfig; +import org.junit.Test; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; + +@ContextConfiguration(classes = { SecurityWithCsrfConfig.class, ClientWebConfig.class, WebConfig.class, SwaggerConfig.class }) +public class CsrfEnabledIntegrationTest extends CsrfAbstractIntegrationTest { + + @Test + public void givenNoCsrf_whenAddFoo_thenForbidden() throws Exception { + mvc.perform(post("/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo()).with(testUser())).andExpect(status().isForbidden()); + } + + @Test + public void givenCsrf_whenAddFoo_thenCreated() throws Exception { + mvc.perform(post("/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo()).with(testUser()).with(csrf())).andExpect(status().isCreated()); + } + +}