Prevent Save @Transient Authentication with existing HttpSession

Previously, @Transient Authentication would get saved if an existing
HttpSession existed but it shouldn't.

This commit always prevents @Transient Authentication from being saved.

Closes gh-9992
This commit is contained in:
Rob Winch 2021-06-23 14:27:28 -05:00
parent 4318a51971
commit 96a6fef820
2 changed files with 24 additions and 5 deletions

View File

@ -233,6 +233,9 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
}
private boolean isTransientAuthentication(Authentication authentication) {
if (authentication == null) {
return false;
}
return AnnotationUtils.getAnnotation(authentication.getClass(), Transient.class) != null;
}
@ -327,6 +330,9 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
@Override
protected void saveContext(SecurityContext context) {
final Authentication authentication = context.getAuthentication();
if (isTransientAuthentication(authentication)) {
return;
}
HttpSession httpSession = this.request.getSession(false);
String springSecurityContextKey = HttpSessionSecurityContextRepository.this.springSecurityContextKey;
// See SEC-776
@ -348,7 +354,7 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
}
return;
}
httpSession = (httpSession != null) ? httpSession : createNewSessionIfAllowed(context, authentication);
httpSession = (httpSession != null) ? httpSession : createNewSessionIfAllowed(context);
// If HttpSession exists, store current SecurityContext but only if it has
// actually changed in this thread (see SEC-37, SEC-1307, SEC-1528)
if (httpSession != null) {
@ -369,10 +375,7 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
|| context.getAuthentication() != this.authBeforeExecution;
}
private HttpSession createNewSessionIfAllowed(SecurityContext context, Authentication authentication) {
if (isTransientAuthentication(authentication)) {
return null;
}
private HttpSession createNewSessionIfAllowed(SecurityContext context) {
if (this.httpSessionExistedAtStartOfRequest) {
this.logger.debug("HttpSession is now null, but was not null at start of request; "
+ "session was invalidated, so do not create a new session");

View File

@ -21,6 +21,7 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Collections;
import javax.servlet.Filter;
import javax.servlet.ServletException;
@ -614,6 +615,21 @@ public class HttpSessionSecurityContextRepositoryTests {
assertThat(session).isNull();
}
@Test
public void saveContextWhenTransientAuthenticationAndSessionExistsThenSkipped() {
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
MockHttpServletRequest request = new MockHttpServletRequest();
request.getSession(); // ensure the session exists
MockHttpServletResponse response = new MockHttpServletResponse();
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
SecurityContext context = repo.loadContext(holder);
SomeTransientAuthentication authentication = new SomeTransientAuthentication();
context.setAuthentication(authentication);
repo.saveContext(context, holder.getRequest(), holder.getResponse());
MockHttpSession session = (MockHttpSession) request.getSession(false);
assertThat(Collections.list(session.getAttributeNames())).isEmpty();
}
@Test
public void saveContextWhenTransientAuthenticationWithCustomAnnotationThenSkipped() {
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();