From ca02d8a4f8e1d2434dde72a79bce750685f6561e Mon Sep 17 00:00:00 2001 From: Josh Cummings Date: Fri, 18 Jan 2019 16:56:13 -0700 Subject: [PATCH] NamespaceLogoutTests groovy->java Issue: gh-4939 --- .../NamespaceHttpLogoutTests.groovy | 160 ------------------ .../configurers/NamespaceHttpLogoutTests.java | 159 +++++++++++++++++ 2 files changed, 159 insertions(+), 160 deletions(-) delete mode 100644 config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.groovy create mode 100644 config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.java diff --git a/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.groovy b/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.groovy deleted file mode 100644 index 59789634af..0000000000 --- a/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.groovy +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2002-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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.security.config.annotation.web.configurers; - -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.mock.web.MockFilterChain -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse -import org.springframework.security.access.AccessDecisionManager -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.access.ConfigAttribute -import org.springframework.security.authentication.AnonymousAuthenticationToken -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken -import org.springframework.security.config.annotation.BaseSpringSpec -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.BaseWebConfig; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.core.authority.AuthorityUtils; -import org.springframework.security.core.context.SecurityContextImpl -import org.springframework.security.web.AuthenticationEntryPoint -import org.springframework.security.web.FilterChainProxy -import org.springframework.security.web.FilterInvocation -import org.springframework.security.web.access.AccessDeniedHandler; -import org.springframework.security.web.access.AccessDeniedHandlerImpl; -import org.springframework.security.web.access.ExceptionTranslationFilter -import org.springframework.security.web.access.intercept.FilterSecurityInterceptor -import org.springframework.security.web.authentication.AnonymousAuthenticationFilter; -import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; -import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler -import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import org.springframework.security.web.authentication.WebAuthenticationDetailsSource -import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler; -import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; -import org.springframework.security.web.context.HttpRequestResponseHolder -import org.springframework.security.web.context.HttpSessionSecurityContextRepository; -import org.springframework.security.web.context.NullSecurityContextRepository; -import org.springframework.security.web.context.SecurityContextPersistenceFilter -import org.springframework.security.web.jaasapi.JaasApiIntegrationFilter; -import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher -import org.springframework.security.web.util.matcher.AnyRequestMatcher; -import org.springframework.security.web.util.matcher.RequestMatcher - -/** - * Tests to verify that all the functionality of attributes is present - * - * @author Rob Winch - * - */ -public class NamespaceHttpLogoutTests extends BaseSpringSpec { - - def "http/logout"() { - setup: - loadConfig(HttpLogoutConfig) - login() - request.servletPath = "/logout" - request.method = "POST" - when: - springSecurityFilterChain.doFilter(request,response,chain) - then: - !authenticated() - !request.getSession(false) - response.redirectedUrl == "/login?logout" - !response.getCookies() - } - - @Configuration - static class HttpLogoutConfig extends BaseWebConfig { - protected void configure(HttpSecurity http) throws Exception { - } - } - - def "http/logout custom"() { - setup: - loadConfig(CustomHttpLogoutConfig) - login() - request.servletPath = "/custom-logout" - request.method = "POST" - when: - springSecurityFilterChain.doFilter(request,response,chain) - then: - !authenticated() - request.getSession(false) - response.redirectedUrl == "/logout-success" - response.getCookies().length == 1 - response.getCookies()[0].name == "remove" - response.getCookies()[0].maxAge == 0 - } - - @Configuration - static class CustomHttpLogoutConfig extends BaseWebConfig { - protected void configure(HttpSecurity http) throws Exception { - http - .logout() - .deleteCookies("remove") // logout@delete-cookies - .invalidateHttpSession(false) // logout@invalidate-session=false (default is true) - .logoutUrl("/custom-logout") // logout@logout-url (default is /logout) - .logoutSuccessUrl("/logout-success") // logout@success-url (default is /login?logout) - } - } - - def "http/logout@success-handler-ref"() { - setup: - loadConfig(SuccessHandlerRefHttpLogoutConfig) - login() - request.servletPath = "/logout" - request.method = "POST" - when: - springSecurityFilterChain.doFilter(request,response,chain) - then: - !authenticated() - !request.getSession(false) - response.redirectedUrl == "/SuccessHandlerRefHttpLogoutConfig" - !response.getCookies() - } - - @Configuration - static class SuccessHandlerRefHttpLogoutConfig extends BaseWebConfig { - protected void configure(HttpSecurity http) throws Exception { - SimpleUrlLogoutSuccessHandler logoutSuccessHandler = new SimpleUrlLogoutSuccessHandler(defaultTargetUrl:"/SuccessHandlerRefHttpLogoutConfig") - http - .logout() - .logoutSuccessHandler(logoutSuccessHandler) - } - } - - def login(String username="user", String role="ROLE_USER") { - HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository() - HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response) - repo.loadContext(requestResponseHolder) - repo.saveContext(new SecurityContextImpl(authentication: new UsernamePasswordAuthenticationToken(username, null, AuthorityUtils.createAuthorityList(role))), requestResponseHolder.request, requestResponseHolder.response) - } - - def authenticated() { - HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response) - new HttpSessionSecurityContextRepository().loadContext(requestResponseHolder)?.authentication?.authenticated - } -} diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.java new file mode 100644 index 0000000000..065e0427ab --- /dev/null +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceHttpLogoutTests.java @@ -0,0 +1,159 @@ +/* + * Copyright 2002-2019 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.config.annotation.web.configurers; + +import java.util.Objects; +import java.util.Optional; +import java.util.function.Predicate; +import javax.servlet.http.HttpSession; + +import org.assertj.core.api.Condition; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +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.config.test.SpringTestRule; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultMatcher; + +import static org.assertj.core.api.Assertions.assertThat; +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.cookie; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; + +/** + * Tests to verify that all the functionality of attributes is present + * + * @author Rob Winch + * @author Josh Cummings + */ +@RunWith(SpringRunner.class) +@SecurityTestExecutionListeners +public class NamespaceHttpLogoutTests { + + @Rule + public final SpringTestRule spring = new SpringTestRule(); + + @Autowired + MockMvc mvc; + + /** + * http/logout equivalent + */ + @Test + @WithMockUser + public void logoutWhenUsingDefaultsThenMatchesNamespace() throws Exception { + this.spring.register(HttpLogoutConfig.class).autowire(); + + this.mvc.perform(post("/logout").with(csrf())) + .andExpect(authenticated(false)) + .andExpect(redirectedUrl("/login?logout")) + .andExpect(noCookies()) + .andExpect(session(Objects::isNull)); + } + + @EnableWebSecurity + static class HttpLogoutConfig extends WebSecurityConfigurerAdapter { + @Override + protected void configure(HttpSecurity http) throws Exception { + } + } + + /** + * http/logout custom + */ + @Test + @WithMockUser + public void logoutWhenUsingVariousCustomizationsMatchesNamespace() throws Exception { + this.spring.register(CustomHttpLogoutConfig.class).autowire(); + + this.mvc.perform(post("/custom-logout").with(csrf())) + .andExpect(authenticated(false)) + .andExpect(redirectedUrl("/logout-success")) + .andExpect(result -> assertThat(result.getResponse().getCookies()).hasSize(1)) + .andExpect(cookie().maxAge("remove", 0)) + .andExpect(session(Objects::nonNull)); + } + + @EnableWebSecurity + static class CustomHttpLogoutConfig extends WebSecurityConfigurerAdapter { + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .logout() + .deleteCookies("remove") // logout@delete-cookies + .invalidateHttpSession(false) // logout@invalidate-session=false (default is true) + .logoutUrl("/custom-logout") // logout@logout-url (default is /logout) + .logoutSuccessUrl("/logout-success"); // logout@success-url (default is /login?logout) + } + } + + /** + * http/logout@success-handler-ref + */ + @Test + @WithMockUser + public void logoutWhenUsingSuccessHandlerRefThenMatchesNamespace() throws Exception { + this.spring.register(SuccessHandlerRefHttpLogoutConfig.class).autowire(); + + this.mvc.perform(post("/logout").with(csrf())) + .andExpect(authenticated(false)) + .andExpect(redirectedUrl("/SuccessHandlerRefHttpLogoutConfig")) + .andExpect(noCookies()) + .andExpect(session(Objects::isNull)); + } + + @EnableWebSecurity + static class SuccessHandlerRefHttpLogoutConfig extends WebSecurityConfigurerAdapter { + @Override + protected void configure(HttpSecurity http) throws Exception { + SimpleUrlLogoutSuccessHandler logoutSuccessHandler = + new SimpleUrlLogoutSuccessHandler(); + logoutSuccessHandler.setDefaultTargetUrl("/SuccessHandlerRefHttpLogoutConfig"); + + http + .logout() + .logoutSuccessHandler(logoutSuccessHandler); + } + } + + ResultMatcher authenticated(boolean authenticated) { + return result -> assertThat( + Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication()) + .map(Authentication::isAuthenticated) + .orElse(false)).isEqualTo(authenticated); + } + + ResultMatcher noCookies() { + return result -> assertThat(result.getResponse().getCookies()).isEmpty(); + } + + ResultMatcher session(Predicate sessionPredicate) { + return result -> assertThat(result.getRequest().getSession(false)) + .is(new Condition(sessionPredicate, "sessionPredicate failed")); + } +}