Skip to content

Commit 086b105

Browse files
raphaelDLjzheaux
authored andcommitted
Remove Servlet 2.5 Support for Session Fixation
This commit removes existence validation of a method only available in Servlet 3.1. Spring Framework baseline is Servlet 3.1 so is not longer required. Fixes: gh-6259
1 parent 4123d96 commit 086b105

File tree

7 files changed

+32
-107
lines changed

7 files changed

+32
-107
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java

+3-11
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,7 @@ public SessionManagementConfigurer<H> sessionCreationPolicy(
212212

213213
/**
214214
* Allows explicitly specifying the {@link SessionAuthenticationStrategy}.
215-
* The default is to use {@link SessionFixationProtectionStrategy} for Servlet 3.1 or
216-
* {@link ChangeSessionIdAuthenticationStrategy} for Servlet 3.1+.
215+
* The default is to use {@link ChangeSessionIdAuthenticationStrategy}.
217216
* If restricting the maximum number of sessions is configured, then
218217
* {@link CompositeSessionAuthenticationStrategy} delegating to
219218
* {@link ConcurrentSessionControlAuthenticationStrategy},
@@ -305,13 +304,11 @@ public SessionManagementConfigurer<H> migrateSession() {
305304

306305
/**
307306
* Specifies that the Servlet container-provided session fixation protection
308-
* should be used. When a session authenticates, the Servlet 3.1 method
307+
* should be used. When a session authenticates, the Servlet method
309308
* {@code HttpServletRequest#changeSessionId()} is called to change the session ID
310-
* and retain all session attributes. Using this option in a Servlet 3.0 or older
311-
* container results in an {@link IllegalStateException}.
309+
* and retain all session attributes.
312310
*
313311
* @return the {@link SessionManagementConfigurer} for further customizations
314-
* @throws IllegalStateException if the container is not Servlet 3.1 or newer.
315312
*/
316313
public SessionManagementConfigurer<H> changeSessionId() {
317314
setSessionFixationAuthenticationStrategy(
@@ -664,11 +661,6 @@ private boolean isConcurrentSessionControlEnabled() {
664661
* @return the default {@link SessionAuthenticationStrategy} for session fixation
665662
*/
666663
private static SessionAuthenticationStrategy createDefaultSessionFixationProtectionStrategy() {
667-
try {
668664
return new ChangeSessionIdAuthenticationStrategy();
669-
}
670-
catch (IllegalStateException e) {
671-
return new SessionFixationProtectionStrategy();
672-
}
673665
}
674666
}

config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java

+1-7
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@
1515
*/
1616
package org.springframework.security.config.http;
1717

18-
import java.lang.reflect.Method;
1918
import java.util.ArrayList;
2019
import java.util.List;
2120

2221
import javax.servlet.ServletRequest;
23-
import javax.servlet.http.HttpServletRequest;
2422

2523
import org.w3c.dom.Element;
2624

@@ -73,7 +71,6 @@
7371
import org.springframework.security.web.session.SimpleRedirectSessionInformationExpiredStrategy;
7472
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
7573
import org.springframework.util.ClassUtils;
76-
import org.springframework.util.ReflectionUtils;
7774
import org.springframework.util.StringUtils;
7875
import org.springframework.util.xml.DomUtils;
7976

@@ -350,10 +347,7 @@ private void createSessionManagementFilters() {
350347
}
351348

352349
if (!StringUtils.hasText(sessionFixationAttribute)) {
353-
Method changeSessionIdMethod = ReflectionUtils.findMethod(
354-
HttpServletRequest.class, "changeSessionId");
355-
sessionFixationAttribute = changeSessionIdMethod == null ? OPT_SESSION_FIXATION_MIGRATE_SESSION
356-
: OPT_CHANGE_SESSION_ID;
350+
sessionFixationAttribute = OPT_CHANGE_SESSION_ID;
357351
}
358352
else if (StringUtils.hasText(sessionAuthStratRef)) {
359353
pc.getReaderContext().error(

config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java

+6-17
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,13 @@
1717

1818
import java.lang.reflect.Method;
1919
import javax.servlet.Filter;
20-
import javax.servlet.http.HttpServletRequest;
2120

2221
import org.junit.After;
2322
import org.junit.Before;
2423
import org.junit.Test;
2524
import org.junit.runner.RunWith;
2625
import org.mockito.Mock;
2726
import org.powermock.core.classloader.annotations.PowerMockIgnore;
28-
import org.powermock.core.classloader.annotations.PrepareForTest;
2927
import org.powermock.modules.junit4.PowerMockRunner;
3028

3129
import org.springframework.context.ConfigurableApplicationContext;
@@ -44,21 +42,14 @@
4442
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
4543
import org.springframework.security.web.csrf.CsrfToken;
4644
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
47-
import org.springframework.util.ReflectionUtils;
4845

49-
import static org.mockito.Matchers.any;
50-
import static org.mockito.Matchers.same;
51-
import static org.powermock.api.mockito.PowerMockito.mock;
52-
import static org.powermock.api.mockito.PowerMockito.spy;
53-
import static org.powermock.api.mockito.PowerMockito.verifyStatic;
54-
import static org.powermock.api.mockito.PowerMockito.when;
46+
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
5547

5648
/**
5749
*
5850
* @author Rob Winch
5951
*/
6052
@RunWith(PowerMockRunner.class)
61-
@PrepareForTest({ ReflectionUtils.class, Method.class })
6253
@PowerMockIgnore({ "org.w3c.dom.*", "org.xml.sax.*", "org.apache.xerces.*", "javax.xml.parsers.*" })
6354
public class SessionManagementConfigurerServlet31Tests {
6455
@Mock
@@ -87,10 +78,9 @@ public void teardown() {
8778
}
8879

8980
@Test
90-
public void changeSessionIdDefaultsInServlet31Plus() throws Exception {
91-
spy(ReflectionUtils.class);
92-
Method method = mock(Method.class);
81+
public void changeSessionIdThenPreserveParameters() throws Exception {
9382
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
83+
String id = request.getSession().getId();
9484
request.getSession();
9585
request.setServletPath("/login");
9686
request.setMethod("POST");
@@ -100,15 +90,14 @@ public void changeSessionIdDefaultsInServlet31Plus() throws Exception {
10090
CsrfToken token = repository.generateToken(request);
10191
repository.saveToken(token, request, response);
10292
request.setParameter(token.getParameterName(), token.getToken());
103-
when(ReflectionUtils.findMethod(HttpServletRequest.class, "changeSessionId"))
104-
.thenReturn(method);
93+
request.getSession().setAttribute("attribute1", "value1");
10594

10695
loadConfig(SessionManagementDefaultSessionFixationServlet31Config.class);
10796

10897
springSecurityFilterChain.doFilter(request, response, chain);
10998

110-
verifyStatic(ReflectionUtils.class);
111-
ReflectionUtils.invokeMethod(same(method), any(HttpServletRequest.class));
99+
assertThat(!request.getSession().getId().equals(id));
100+
assertThat(request.getSession().getAttribute("attribute1").equals("value1"));
112101
}
113102

114103
@EnableWebSecurity

config/src/test/java/org/springframework/security/config/http/SessionManagementConfigServlet31Tests.java

+14-20
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
import java.lang.reflect.Method;
1919
import javax.servlet.Filter;
20-
import javax.servlet.http.HttpServletRequest;
2120

2221
import org.junit.After;
2322
import org.junit.Before;
@@ -39,12 +38,7 @@
3938
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
4039
import org.springframework.util.ReflectionUtils;
4140

42-
import static org.mockito.Matchers.any;
43-
import static org.mockito.Matchers.same;
44-
import static org.powermock.api.mockito.PowerMockito.mock;
45-
import static org.powermock.api.mockito.PowerMockito.spy;
46-
import static org.powermock.api.mockito.PowerMockito.verifyStatic;
47-
import static org.powermock.api.mockito.PowerMockito.when;
41+
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
4842

4943
/**
5044
* @author Rob Winch
@@ -86,40 +80,40 @@ public void teardown() {
8680
}
8781

8882
@Test
89-
public void changeSessionIdDefaultsInServlet31Plus() throws Exception {
90-
spy(ReflectionUtils.class);
91-
Method method = mock(Method.class);
83+
public void changeSessionIdThenPreserveParameters() throws Exception {
9284
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
9385
request.getSession();
9486
request.setServletPath("/login");
9587
request.setMethod("POST");
9688
request.setParameter("username", "user");
9789
request.setParameter("password", "password");
98-
when(ReflectionUtils.findMethod(HttpServletRequest.class, "changeSessionId"))
99-
.thenReturn(method);
90+
91+
request.getSession().setAttribute("attribute1", "value1");
92+
93+
String id = request.getSession().getId();
10094

10195
loadContext("<http>\n" + " <form-login/>\n"
10296
+ " <session-management/>\n" + " <csrf disabled='true'/>\n"
10397
+ " </http>" + XML_AUTHENTICATION_MANAGER);
10498

10599
springSecurityFilterChain.doFilter(request, response, chain);
106100

107-
verifyStatic(ReflectionUtils.class);
108-
ReflectionUtils.invokeMethod(same(method), any(HttpServletRequest.class));
101+
102+
assertThat(!request.getSession().getId().equals(id));
103+
assertThat(request.getSession().getAttribute("attribute1").equals("value1"));
109104
}
110105

111106
@Test
112107
public void changeSessionId() throws Exception {
113-
spy(ReflectionUtils.class);
114-
Method method = mock(Method.class);
108+
115109
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
116110
request.getSession();
117111
request.setServletPath("/login");
118112
request.setMethod("POST");
119113
request.setParameter("username", "user");
120114
request.setParameter("password", "password");
121-
when(ReflectionUtils.findMethod(HttpServletRequest.class, "changeSessionId"))
122-
.thenReturn(method);
115+
116+
String id = request.getSession().getId();
123117

124118
loadContext("<http>\n"
125119
+ " <form-login/>\n"
@@ -129,8 +123,8 @@ public void changeSessionId() throws Exception {
129123

130124
springSecurityFilterChain.doFilter(request, response, chain);
131125

132-
verifyStatic(ReflectionUtils.class);
133-
ReflectionUtils.invokeMethod(same(method), any(HttpServletRequest.class));
126+
assertThat(!request.getSession().getId().equals(id));
127+
134128
}
135129

136130
private void loadContext(String context) {

web/src/main/java/org/springframework/security/web/authentication/session/ChangeSessionIdAuthenticationStrategy.java

+2-17
Original file line numberDiff line numberDiff line change
@@ -15,33 +15,18 @@
1515
*/
1616
package org.springframework.security.web.authentication.session;
1717

18-
import java.lang.reflect.Method;
19-
2018
import javax.servlet.http.HttpServletRequest;
2119
import javax.servlet.http.HttpSession;
2220

23-
import org.springframework.util.ReflectionUtils;
24-
2521
/**
2622
* Uses {@code HttpServletRequest.changeSessionId()} to protect against session fixation
27-
* attacks. This is the default implementation for Servlet 3.1+.
23+
* attacks. This is the default implementation.
2824
*
2925
* @author Rob Winch
3026
* @since 3.2
3127
*/
3228
public final class ChangeSessionIdAuthenticationStrategy
3329
extends AbstractSessionFixationProtectionStrategy {
34-
private final Method changeSessionIdMethod;
35-
36-
public ChangeSessionIdAuthenticationStrategy() {
37-
Method changeSessionIdMethod = ReflectionUtils
38-
.findMethod(HttpServletRequest.class, "changeSessionId");
39-
if (changeSessionIdMethod == null) {
40-
throw new IllegalStateException(
41-
"HttpServletRequest.changeSessionId is undefined. Are you using a Servlet 3.1+ environment?");
42-
}
43-
this.changeSessionIdMethod = changeSessionIdMethod;
44-
}
4530

4631
/*
4732
* (non-Javadoc)
@@ -52,7 +37,7 @@ public ChangeSessionIdAuthenticationStrategy() {
5237
*/
5338
@Override
5439
HttpSession applySessionFixation(HttpServletRequest request) {
55-
ReflectionUtils.invokeMethod(this.changeSessionIdMethod, request);
40+
request.changeSessionId();
5641
return request.getSession();
5742
}
5843
}

web/src/main/java/org/springframework/security/web/authentication/session/SessionFixationProtectionStrategy.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import javax.servlet.http.HttpSession;
2525

2626
/**
27-
* The default implementation of {@link SessionAuthenticationStrategy} when using &lt;
27+
* The implementation of {@link SessionAuthenticationStrategy} when using &lt;
2828
* Servlet 3.1.
2929
* <p>
3030
* Creates a new session for the newly authenticated user if they already have a session

web/src/test/java/org/springframework/security/web/authentication/session/ChangeSessionIdAuthenticationStrategyTests.java

+5-34
Original file line numberDiff line numberDiff line change
@@ -15,55 +15,26 @@
1515
*/
1616
package org.springframework.security.web.authentication.session;
1717

18-
import static org.mockito.Matchers.*;
19-
import static org.powermock.api.mockito.PowerMockito.*;
20-
21-
import java.lang.reflect.Method;
22-
23-
import javax.servlet.http.HttpServletRequest;
24-
18+
import org.junit.Assert;
2519
import org.junit.Test;
2620
import org.junit.runner.RunWith;
27-
import org.mockito.Mock;
28-
import org.powermock.core.classloader.annotations.PrepareForTest;
2921
import org.powermock.modules.junit4.PowerMockRunner;
3022
import org.springframework.mock.web.MockHttpServletRequest;
31-
import org.springframework.util.ReflectionUtils;
3223

3324
/**
3425
* @author Rob Winch
3526
*
3627
*/
3728
@RunWith(PowerMockRunner.class)
38-
@PrepareForTest({ ReflectionUtils.class, Method.class })
3929
public class ChangeSessionIdAuthenticationStrategyTests {
40-
@Mock
41-
private Method method;
42-
43-
@Test(expected = IllegalStateException.class)
44-
public void constructChangeIdMethodNotFound() {
45-
spy(ReflectionUtils.class);
46-
MockHttpServletRequest request = new MockHttpServletRequest();
47-
request.getSession();
48-
when(ReflectionUtils.findMethod(HttpServletRequest.class, "changeSessionId"))
49-
.thenReturn(null);
50-
51-
new ChangeSessionIdAuthenticationStrategy();
52-
}
5330

5431
@Test
55-
public void applySessionFixation() throws Exception {
56-
spy(ReflectionUtils.class);
57-
Method method = mock(Method.class);
32+
public void applySessionFixation() {
5833
MockHttpServletRequest request = new MockHttpServletRequest();
59-
request.getSession();
60-
when(ReflectionUtils.findMethod(HttpServletRequest.class, "changeSessionId"))
61-
.thenReturn(method);
34+
String id = request.getSession().getId();
6235

63-
new ChangeSessionIdAuthenticationStrategy().applySessionFixation(request);
36+
new ChangeSessionIdAuthenticationStrategy().applySessionFixation(request);
6437

65-
verifyStatic(ReflectionUtils.class);
66-
ReflectionUtils.invokeMethod(same(method), eq(request));
38+
Assert.assertNotEquals(id, request.getSession().getId());
6739
}
68-
6940
}

0 commit comments

Comments
 (0)