浏览代码

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
Rob Winch 4 年之前
父节点
当前提交
bd34d70f97

+ 8 - 5
web/src/main/java/org/springframework/security/web/context/HttpSessionSecurityContextRepository.java

@@ -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");

+ 16 - 0
web/src/test/java/org/springframework/security/web/context/HttpSessionSecurityContextRepositoryTests.java

@@ -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 jakarta.servlet.Filter;
 import jakarta.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();