Merge branch '6.0.x'
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2023 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.
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.security.config.annotation.web.configurers;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.http.HttpHeaders;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
@@ -25,6 +27,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.SecurityContextChangedListenerConfig;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
@@ -39,6 +43,8 @@ import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.RememberMeServices;
|
||||
import org.springframework.security.web.authentication.logout.LogoutFilter;
|
||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
|
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||
import org.springframework.security.web.context.SecurityContextRepository;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
@@ -48,6 +54,7 @@ import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
|
||||
@@ -324,6 +331,80 @@ public class LogoutConfigurerTests {
|
||||
this.mvc.perform(post("/logout").with(csrf())).andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logoutWhenCustomSecurityContextRepositoryThenUses() throws Exception {
|
||||
CustomSecurityContextRepositoryConfig.repository = mock(SecurityContextRepository.class);
|
||||
this.spring.register(CustomSecurityContextRepositoryConfig.class).autowire();
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder logoutRequest = post("/logout")
|
||||
.with(csrf())
|
||||
.with(user("user"))
|
||||
.header(HttpHeaders.ACCEPT, MediaType.TEXT_HTML_VALUE);
|
||||
this.mvc.perform(logoutRequest)
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/login?logout"));
|
||||
// @formatter:on
|
||||
int invocationCount = 2; // 1 from user() post processor and 1 from
|
||||
// SecurityContextLogoutHandler
|
||||
verify(CustomSecurityContextRepositoryConfig.repository, times(invocationCount)).saveContext(any(),
|
||||
any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logoutWhenNoSecurityContextRepositoryThenHttpSessionSecurityContextRepository() throws Exception {
|
||||
this.spring.register(InvalidateHttpSessionFalseConfig.class).autowire();
|
||||
MockHttpSession session = mock(MockHttpSession.class);
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder logoutRequest = post("/logout")
|
||||
.with(csrf())
|
||||
.with(user("user"))
|
||||
.session(session)
|
||||
.header(HttpHeaders.ACCEPT, MediaType.TEXT_HTML_VALUE);
|
||||
this.mvc.perform(logoutRequest)
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("/login?logout"))
|
||||
.andReturn();
|
||||
// @formatter:on
|
||||
verify(session).removeAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class InvalidateHttpSessionFalseConfig {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.logout((logout) -> logout.invalidateHttpSession(false))
|
||||
.securityContext((context) -> context.requireExplicitSave(true));
|
||||
return http.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class CustomSecurityContextRepositoryConfig {
|
||||
|
||||
static SecurityContextRepository repository;
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.logout(Customizer.withDefaults())
|
||||
.securityContext((context) -> context
|
||||
.requireExplicitSave(true)
|
||||
.securityContextRepository(repository)
|
||||
);
|
||||
return http.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class NullLogoutSuccessHandlerConfig {
|
||||
|
||||
Reference in New Issue
Block a user