NamespaceSessionManagementTests groovy->java
Issue: gh-4939
This commit is contained in:
parent
329999b54a
commit
ee8182dceb
|
@ -1,229 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2013 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
|
||||
*
|
||||
* https://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 org.springframework.context.ApplicationListener
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.mock.web.MockHttpSession
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken
|
||||
import org.springframework.security.config.annotation.BaseSpringSpec
|
||||
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.core.session.SessionRegistry
|
||||
import org.springframework.security.web.authentication.session.AbstractSessionFixationProtectionStrategy;
|
||||
import org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy;
|
||||
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy
|
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy
|
||||
import org.springframework.security.web.authentication.session.SessionFixationProtectionEvent
|
||||
import org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy
|
||||
import org.springframework.security.web.session.ConcurrentSessionFilter
|
||||
import org.springframework.security.web.session.SessionManagementFilter
|
||||
import org.springframework.security.web.session.InvalidSessionStrategy
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
class NamespaceSessionManagementTests extends BaseSpringSpec {
|
||||
|
||||
def "http/session-management"() {
|
||||
when:
|
||||
loadConfig(SessionManagementConfig)
|
||||
then:
|
||||
findSessionAuthenticationStrategy(AbstractSessionFixationProtectionStrategy)
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class SessionManagementConfig extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
// enabled by default
|
||||
}
|
||||
}
|
||||
|
||||
def "http/session-management custom"() {
|
||||
setup:
|
||||
CustomSessionManagementConfig.SR = Mock(SessionRegistry)
|
||||
when:
|
||||
loadConfig(CustomSessionManagementConfig)
|
||||
def concurrentStrategy = findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies[0]
|
||||
then:
|
||||
findFilter(SessionManagementFilter).invalidSessionStrategy.destinationUrl == "/invalid-session"
|
||||
findFilter(SessionManagementFilter).failureHandler.defaultFailureUrl == "/session-auth-error"
|
||||
concurrentStrategy.maximumSessions == 1
|
||||
concurrentStrategy.exceptionIfMaximumExceeded
|
||||
concurrentStrategy.sessionRegistry == CustomSessionManagementConfig.SR
|
||||
findFilter(ConcurrentSessionFilter).sessionInformationExpiredStrategy.destinationUrl == "/expired-session"
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class CustomSessionManagementConfig extends WebSecurityConfigurerAdapter {
|
||||
static SessionRegistry SR
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.sessionManagement()
|
||||
.invalidSessionUrl("/invalid-session") // session-management@invalid-session-url
|
||||
.sessionAuthenticationErrorUrl("/session-auth-error") // session-management@session-authentication-error-url
|
||||
.maximumSessions(1) // session-management/concurrency-control@max-sessions
|
||||
.maxSessionsPreventsLogin(true) // session-management/concurrency-control@error-if-maximum-exceeded
|
||||
.expiredUrl("/expired-session") // session-management/concurrency-control@expired-url
|
||||
.sessionRegistry(SR) // session-management/concurrency-control@session-registry-ref
|
||||
}
|
||||
}
|
||||
|
||||
// gh-3371
|
||||
def "http/session-management custom invalidationstrategy"() {
|
||||
setup:
|
||||
InvalidSessionStrategyConfig.ISS = Mock(InvalidSessionStrategy)
|
||||
when:
|
||||
loadConfig(InvalidSessionStrategyConfig)
|
||||
then:
|
||||
findFilter(SessionManagementFilter).invalidSessionStrategy == InvalidSessionStrategyConfig.ISS
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class InvalidSessionStrategyConfig extends WebSecurityConfigurerAdapter {
|
||||
static InvalidSessionStrategy ISS
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.sessionManagement()
|
||||
.invalidSessionStrategy(ISS)
|
||||
}
|
||||
}
|
||||
|
||||
def "http/session-management refs"() {
|
||||
setup:
|
||||
RefsSessionManagementConfig.SAS = Mock(SessionAuthenticationStrategy)
|
||||
when:
|
||||
loadConfig(RefsSessionManagementConfig)
|
||||
then:
|
||||
findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies.find { it == RefsSessionManagementConfig.SAS }
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class RefsSessionManagementConfig extends WebSecurityConfigurerAdapter {
|
||||
static SessionAuthenticationStrategy SAS
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.sessionManagement()
|
||||
.sessionAuthenticationStrategy(SAS) // session-management@session-authentication-strategy-ref
|
||||
}
|
||||
}
|
||||
|
||||
def "http/session-management@session-fixation-protection=none"() {
|
||||
when:
|
||||
loadConfig(SFPNoneSessionManagementConfig)
|
||||
then:
|
||||
findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies.find { it instanceof NullAuthenticatedSessionStrategy }
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class SFPNoneSessionManagementConfig extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.sessionManagement()
|
||||
.sessionAuthenticationStrategy(new NullAuthenticatedSessionStrategy())
|
||||
}
|
||||
}
|
||||
|
||||
def "http/session-management@session-fixation-protection=migrateSession (default)"() {
|
||||
when:
|
||||
loadConfig(SFPMigrateSessionManagementConfig)
|
||||
then:
|
||||
if(isChangeSession()) {
|
||||
findSessionAuthenticationStrategy(ChangeSessionIdAuthenticationStrategy)
|
||||
} else {
|
||||
findSessionAuthenticationStrategy(SessionFixationProtectionStrategy).migrateSessionAttributes
|
||||
}
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class SFPMigrateSessionManagementConfig extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.sessionManagement()
|
||||
}
|
||||
}
|
||||
|
||||
def "SEC-2913: Default JavaConfig session fixation AuthenticationStrategy has NullEventPublisher"() {
|
||||
setup:
|
||||
loadConfig(SFPPostProcessedConfig)
|
||||
when:
|
||||
findSessionAuthenticationStrategy(AbstractSessionFixationProtectionStrategy).onSessionChange("id", new MockHttpSession(), new TestingAuthenticationToken("u","p","ROLE_USER"))
|
||||
then:
|
||||
context.getBean(MockEventListener).events
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class SFPPostProcessedConfig extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.sessionManagement()
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MockEventListener eventListener() {
|
||||
new MockEventListener()
|
||||
}
|
||||
}
|
||||
|
||||
def "http/session-management@session-fixation-protection=newSession"() {
|
||||
when:
|
||||
loadConfig(SFPNewSessionSessionManagementConfig)
|
||||
then:
|
||||
!findSessionAuthenticationStrategy(SessionFixationProtectionStrategy).migrateSessionAttributes
|
||||
}
|
||||
|
||||
def findSessionAuthenticationStrategy(def c) {
|
||||
findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies.find { c.isAssignableFrom(it.class) }
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class SFPNewSessionSessionManagementConfig extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.sessionManagement()
|
||||
.sessionFixation()
|
||||
.newSession()
|
||||
}
|
||||
}
|
||||
|
||||
static class MockEventListener implements ApplicationListener<SessionFixationProtectionEvent> {
|
||||
List<SessionFixationProtectionEvent> events = []
|
||||
|
||||
public void onApplicationEvent(SessionFixationProtectionEvent event) {
|
||||
events.add(event)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
boolean isChangeSession() {
|
||||
try {
|
||||
new ChangeSessionIdAuthenticationStrategy()
|
||||
return true
|
||||
} catch(Exception e) {}
|
||||
return false
|
||||
}
|
||||
}
|
|
@ -0,0 +1,471 @@
|
|||
/*
|
||||
* 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
|
||||
*
|
||||
* https://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.security.Principal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
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.session.SessionInformation;
|
||||
import org.springframework.security.core.session.SessionRegistry;
|
||||
import org.springframework.security.core.session.SessionRegistryImpl;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy;
|
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationException;
|
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
|
||||
import org.springframework.security.web.authentication.session.SessionFixationProtectionEvent;
|
||||
import org.springframework.security.web.session.InvalidSessionStrategy;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.ResultMatcher;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Josh Cummings
|
||||
*/
|
||||
public class NamespaceSessionManagementTests {
|
||||
|
||||
@Rule
|
||||
public final SpringTestRule spring = new SpringTestRule();
|
||||
|
||||
@Autowired
|
||||
MockMvc mvc;
|
||||
|
||||
@Test
|
||||
public void authenticateWhenDefaultSessionManagementThenMatchesNamespace() throws Exception {
|
||||
this.spring.register
|
||||
(SessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class).autowire();
|
||||
|
||||
MockHttpSession session = new MockHttpSession();
|
||||
String sessionId = session.getId();
|
||||
|
||||
MvcResult result =
|
||||
this.mvc.perform(get("/auth")
|
||||
.session(session)
|
||||
.with(httpBasic("user", "password")))
|
||||
.andExpect(session())
|
||||
.andReturn();
|
||||
|
||||
assertThat(result.getRequest().getSession(false).getId()).isNotEqualTo(sessionId);
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class SessionManagementConfig extends WebSecurityConfigurerAdapter {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenUsingInvalidSessionUrlThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(CustomSessionManagementConfig.class).autowire();
|
||||
|
||||
this.mvc.perform(get("/auth")
|
||||
.with(request -> {
|
||||
request.setRequestedSessionIdValid(false);
|
||||
request.setRequestedSessionId("id");
|
||||
return request;
|
||||
}))
|
||||
.andExpect(redirectedUrl("/invalid-session"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void authenticateWhenUsingExpiredUrlThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(CustomSessionManagementConfig.class).autowire();
|
||||
|
||||
MockHttpSession session = new MockHttpSession();
|
||||
SessionInformation sessionInformation = new SessionInformation(new Object(), session.getId(), new Date(0));
|
||||
sessionInformation.expireNow();
|
||||
SessionRegistry sessionRegistry = this.spring.getContext().getBean(SessionRegistry.class);
|
||||
when(sessionRegistry.getSessionInformation(session.getId())).thenReturn(sessionInformation);
|
||||
|
||||
this.mvc.perform(get("/auth").session(session))
|
||||
.andExpect(redirectedUrl("/expired-session"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenUsingMaxSessionsThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(CustomSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class).autowire();
|
||||
|
||||
this.mvc.perform(get("/auth")
|
||||
.with(httpBasic("user", "password")))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
this.mvc.perform(get("/auth")
|
||||
.with(httpBasic("user", "password")))
|
||||
.andExpect(redirectedUrl("/session-auth-error"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenUsingFailureUrlThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(CustomSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class).autowire();
|
||||
|
||||
MockHttpServletRequest mock = spy(MockHttpServletRequest.class);
|
||||
mock.setSession(new MockHttpSession());
|
||||
when(mock.changeSessionId()).thenThrow(SessionAuthenticationException.class);
|
||||
mock.setMethod("GET");
|
||||
|
||||
this.mvc.perform(get("/auth")
|
||||
.with(request -> mock)
|
||||
.with(httpBasic("user", "password")))
|
||||
.andExpect(redirectedUrl("/session-auth-error"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenUsingSessionRegistryThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(CustomSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class).autowire();
|
||||
|
||||
SessionRegistry sessionRegistry = this.spring.getContext().getBean(SessionRegistry.class);
|
||||
|
||||
this.mvc.perform(get("/auth")
|
||||
.with(httpBasic("user", "password")))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
verify(sessionRegistry).registerNewSession(any(String.class), any(Object.class));
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class CustomSessionManagementConfig extends WebSecurityConfigurerAdapter {
|
||||
SessionRegistry sessionRegistry = spy(SessionRegistryImpl.class);
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests()
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.httpBasic()
|
||||
.and()
|
||||
.sessionManagement()
|
||||
.invalidSessionUrl("/invalid-session") // session-management@invalid-session-url
|
||||
.sessionAuthenticationErrorUrl("/session-auth-error") // session-management@session-authentication-error-url
|
||||
.maximumSessions(1) // session-management/concurrency-control@max-sessions
|
||||
.maxSessionsPreventsLogin(true) // session-management/concurrency-control@error-if-maximum-exceeded
|
||||
.expiredUrl("/expired-session") // session-management/concurrency-control@expired-url
|
||||
.sessionRegistry(sessionRegistry()); // session-management/concurrency-control@session-registry-ref
|
||||
}
|
||||
|
||||
@Bean
|
||||
SessionRegistry sessionRegistry() {
|
||||
return this.sessionRegistry;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// gh-3371
|
||||
@Test
|
||||
public void authenticateWhenUsingCustomInvalidSessionStrategyThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(InvalidSessionStrategyConfig.class).autowire();
|
||||
|
||||
this.mvc.perform(get("/auth")
|
||||
.with(request -> {
|
||||
request.setRequestedSessionIdValid(false);
|
||||
request.setRequestedSessionId("id");
|
||||
return request;
|
||||
}))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
verifyBean(InvalidSessionStrategy.class)
|
||||
.onInvalidSessionDetected(any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class InvalidSessionStrategyConfig extends WebSecurityConfigurerAdapter {
|
||||
InvalidSessionStrategy invalidSessionStrategy = mock(InvalidSessionStrategy.class);
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.sessionManagement()
|
||||
.invalidSessionStrategy(invalidSessionStrategy());
|
||||
}
|
||||
|
||||
@Bean
|
||||
InvalidSessionStrategy invalidSessionStrategy() {
|
||||
return this.invalidSessionStrategy;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenUsingCustomSessionAuthenticationStrategyThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(RefsSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class).autowire();
|
||||
|
||||
this.mvc.perform(get("/auth")
|
||||
.with(httpBasic("user", "password")))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
verifyBean(SessionAuthenticationStrategy.class)
|
||||
.onAuthentication(any(Authentication.class),
|
||||
any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class RefsSessionManagementConfig extends WebSecurityConfigurerAdapter {
|
||||
SessionAuthenticationStrategy sessionAuthenticationStrategy =
|
||||
mock(SessionAuthenticationStrategy.class);
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.sessionManagement()
|
||||
.sessionAuthenticationStrategy(sessionAuthenticationStrategy()) // session-management@session-authentication-strategy-ref
|
||||
.and()
|
||||
.httpBasic();
|
||||
}
|
||||
|
||||
@Bean
|
||||
SessionAuthenticationStrategy sessionAuthenticationStrategy() {
|
||||
return this.sessionAuthenticationStrategy;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenNoSessionFixationProtectionThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(SFPNoneSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class).autowire();
|
||||
|
||||
MockHttpSession givenSession = new MockHttpSession();
|
||||
String givenSessionId = givenSession.getId();
|
||||
MockHttpSession resultingSession = (MockHttpSession)
|
||||
this.mvc.perform(get("/auth")
|
||||
.session(givenSession)
|
||||
.with(httpBasic("user", "password")))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn().getRequest().getSession(false);
|
||||
|
||||
assertThat(givenSessionId).isEqualTo(resultingSession.getId());
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class SFPNoneSessionManagementConfig extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.sessionManagement()
|
||||
.sessionAuthenticationStrategy(new NullAuthenticatedSessionStrategy())
|
||||
.and()
|
||||
.httpBasic();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenMigrateSessionFixationProtectionThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(SFPMigrateSessionManagementConfig.class, BasicController.class, UserDetailsServiceConfig.class).autowire();
|
||||
|
||||
MockHttpSession givenSession = new MockHttpSession();
|
||||
String givenSessionId = givenSession.getId();
|
||||
givenSession.setAttribute("name", "value");
|
||||
|
||||
MockHttpSession resultingSession = (MockHttpSession)
|
||||
this.mvc.perform(get("/auth")
|
||||
.session(givenSession)
|
||||
.with(httpBasic("user", "password")))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn().getRequest().getSession(false);
|
||||
|
||||
assertThat(givenSessionId).isNotEqualTo(resultingSession.getId());
|
||||
assertThat(resultingSession.getAttribute("name")).isEqualTo("value");
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class SFPMigrateSessionManagementConfig extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.sessionManagement()
|
||||
.and()
|
||||
.httpBasic();
|
||||
}
|
||||
}
|
||||
|
||||
// SEC-2913
|
||||
@Test
|
||||
public void authenticateWhenUsingSessionFixationProtectionThenUsesNonNullEventPublisher() throws Exception {
|
||||
this.spring.register(SFPPostProcessedConfig.class, UserDetailsServiceConfig.class).autowire();
|
||||
|
||||
this.mvc.perform(get("/auth")
|
||||
.session(new MockHttpSession())
|
||||
.with(httpBasic("user", "password")))
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
verifyBean(MockEventListener.class).onApplicationEvent(any(SessionFixationProtectionEvent.class));
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class SFPPostProcessedConfig extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.sessionManagement()
|
||||
.and()
|
||||
.httpBasic();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MockEventListener eventListener() {
|
||||
return spy(new MockEventListener());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenNewSessionFixationProtectionThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(SFPNewSessionSessionManagementConfig.class, UserDetailsServiceConfig.class).autowire();
|
||||
|
||||
MockHttpSession givenSession = new MockHttpSession();
|
||||
String givenSessionId = givenSession.getId();
|
||||
givenSession.setAttribute("name", "value");
|
||||
|
||||
MockHttpSession resultingSession = (MockHttpSession)
|
||||
this.mvc.perform(get("/auth")
|
||||
.session(givenSession)
|
||||
.with(httpBasic("user", "password")))
|
||||
.andExpect(status().isNotFound())
|
||||
.andReturn().getRequest().getSession(false);
|
||||
|
||||
assertThat(givenSessionId).isNotEqualTo(resultingSession.getId());
|
||||
assertThat(resultingSession.getAttribute("name")).isNull();
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class SFPNewSessionSessionManagementConfig extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.sessionManagement()
|
||||
.sessionFixation().newSession()
|
||||
.and()
|
||||
.httpBasic();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private <T> T verifyBean(Class<T> clazz) {
|
||||
return verify(this.spring.getContext().getBean(clazz));
|
||||
}
|
||||
|
||||
static class MockEventListener implements ApplicationListener<SessionFixationProtectionEvent> {
|
||||
List<SessionFixationProtectionEvent> events = new ArrayList<>();
|
||||
|
||||
public void onApplicationEvent(SessionFixationProtectionEvent event) {
|
||||
this.events.add(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class UserDetailsServiceConfig {
|
||||
@Bean
|
||||
UserDetailsService userDetailsService() {
|
||||
return new InMemoryUserDetailsManager(
|
||||
User.withDefaultPasswordEncoder()
|
||||
.username("user")
|
||||
.password("password")
|
||||
.roles("USER")
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
@RestController
|
||||
static class BasicController {
|
||||
@GetMapping("/")
|
||||
public String ok() {
|
||||
return "ok";
|
||||
}
|
||||
|
||||
@GetMapping("/auth")
|
||||
public String auth(Principal principal) {
|
||||
return principal.getName();
|
||||
}
|
||||
}
|
||||
|
||||
private static SessionResultMatcher session() {
|
||||
return new SessionResultMatcher();
|
||||
}
|
||||
|
||||
private static class SessionResultMatcher implements ResultMatcher {
|
||||
private String id;
|
||||
private Boolean valid;
|
||||
private Boolean exists = true;
|
||||
|
||||
public ResultMatcher exists(boolean exists) {
|
||||
this.exists = exists;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResultMatcher valid(boolean valid) {
|
||||
this.valid = valid;
|
||||
return this.exists(true);
|
||||
}
|
||||
|
||||
public ResultMatcher id(String id) {
|
||||
this.id = id;
|
||||
return this.exists(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void match(MvcResult result) {
|
||||
if (!this.exists) {
|
||||
assertThat(result.getRequest().getSession(false)).isNull();
|
||||
return;
|
||||
}
|
||||
|
||||
assertThat(result.getRequest().getSession(false)).isNotNull();
|
||||
|
||||
MockHttpSession session = (MockHttpSession) result.getRequest().getSession(false);
|
||||
|
||||
if (this.valid != null) {
|
||||
if (this.valid) {
|
||||
assertThat(session.isInvalid()).isFalse();
|
||||
} else {
|
||||
assertThat(session.isInvalid()).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.id != null) {
|
||||
assertThat(session.getId()).isEqualTo(this.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue