Skip to content

Commit 419839d

Browse files
committed
Optimize HttpSessionSecurityContextRepository
Closes gh-9387
1 parent 38e9e8c commit 419839d

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed

web/src/test/java/org/springframework/security/web/context/HttpSessionSecurityContextRepositoryTests.java

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,15 @@
1616

1717
package org.springframework.security.web.context;
1818

19+
import java.io.IOException;
1920
import java.lang.annotation.ElementType;
2021
import java.lang.annotation.Retention;
2122
import java.lang.annotation.RetentionPolicy;
2223
import java.lang.annotation.Target;
24+
import javax.servlet.Filter;
25+
import javax.servlet.ServletException;
2326
import javax.servlet.ServletOutputStream;
27+
import javax.servlet.http.HttpServlet;
2428
import javax.servlet.http.HttpServletRequest;
2529
import javax.servlet.http.HttpServletRequestWrapper;
2630
import javax.servlet.http.HttpServletResponse;
@@ -30,17 +34,22 @@
3034
import org.junit.After;
3135
import org.junit.Test;
3236

37+
import org.springframework.mock.web.MockFilterChain;
3338
import org.springframework.mock.web.MockHttpServletRequest;
3439
import org.springframework.mock.web.MockHttpServletResponse;
3540
import org.springframework.mock.web.MockHttpSession;
3641
import org.springframework.security.authentication.AbstractAuthenticationToken;
3742
import org.springframework.security.authentication.AnonymousAuthenticationToken;
3843
import org.springframework.security.authentication.AuthenticationTrustResolver;
3944
import org.springframework.security.authentication.TestingAuthenticationToken;
45+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
4046
import org.springframework.security.core.Transient;
4147
import org.springframework.security.core.authority.AuthorityUtils;
4248
import org.springframework.security.core.context.SecurityContext;
4349
import org.springframework.security.core.context.SecurityContextHolder;
50+
import org.springframework.security.core.context.SecurityContextImpl;
51+
import org.springframework.security.core.userdetails.User;
52+
import org.springframework.security.core.userdetails.UserDetails;
4453

4554
import static org.assertj.core.api.Assertions.assertThat;
4655
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -174,6 +183,48 @@ public void saveContextCallsSetAttributeIfContextIsModifiedDirectlyDuringRequest
174183
verify(session).setAttribute(SPRING_SECURITY_CONTEXT_KEY, ctx);
175184
}
176185

186+
187+
@Test
188+
public void saveContextWhenSaveNewContextThenOriginalContextThenOriginalContextSaved() throws Exception {
189+
HttpSessionSecurityContextRepository repository = new HttpSessionSecurityContextRepository();
190+
SecurityContextPersistenceFilter securityContextPersistenceFilter = new SecurityContextPersistenceFilter(
191+
repository);
192+
193+
UserDetails original = User.withUsername("user").password("password").roles("USER").build();
194+
SecurityContext originalContext = createSecurityContext(original);
195+
UserDetails impersonate = User.withUserDetails(original).username("impersonate").build();
196+
SecurityContext impersonateContext = createSecurityContext(impersonate);
197+
198+
MockHttpServletRequest mockRequest = new MockHttpServletRequest();
199+
MockHttpServletResponse mockResponse = new MockHttpServletResponse();
200+
201+
Filter saveImpersonateContext = (request, response, chain) -> {
202+
SecurityContextHolder.setContext(impersonateContext);
203+
// ensure the response is committed to trigger save
204+
response.flushBuffer();
205+
chain.doFilter(request, response);
206+
};
207+
Filter saveOriginalContext = (request, response, chain) -> {
208+
SecurityContextHolder.setContext(originalContext);
209+
chain.doFilter(request, response);
210+
};
211+
HttpServlet servlet = new HttpServlet() {
212+
@Override
213+
protected void service(HttpServletRequest req, HttpServletResponse resp)
214+
throws ServletException, IOException {
215+
resp.getWriter().write("Hi");
216+
}
217+
};
218+
219+
SecurityContextHolder.setContext(originalContext);
220+
MockFilterChain chain = new MockFilterChain(servlet, saveImpersonateContext, saveOriginalContext);
221+
222+
securityContextPersistenceFilter.doFilter(mockRequest, mockResponse, chain);
223+
224+
assertThat(mockRequest.getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY))
225+
.isEqualTo(originalContext);
226+
}
227+
177228
@Test
178229
public void nonSecurityContextInSessionIsIgnored() {
179230
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
@@ -668,6 +719,13 @@ public void saveContextWhenTransientAuthenticationWithCustomAnnotationThenSkippe
668719
assertThat(session).isNull();
669720
}
670721

722+
private SecurityContext createSecurityContext(UserDetails userDetails) {
723+
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userDetails,
724+
userDetails.getPassword(), userDetails.getAuthorities());
725+
SecurityContext securityContext = new SecurityContextImpl(token);
726+
return securityContext;
727+
}
728+
671729
@Transient
672730
private static class SomeTransientAuthentication extends AbstractAuthenticationToken {
673731
SomeTransientAuthentication() {

0 commit comments

Comments
 (0)