瀏覽代碼

Adjust createNewSessionIfAllowed to prevent NPE

Ensure that isTransientAuthentication reuses the same authentication object from saveContext

Closes gh-8947
Marcus Hert da Coregio 4 年之前
父節點
當前提交
2a7998d0fc

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

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2021 the original author or authors.
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -348,7 +348,7 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
 				}
 				}
 				return;
 				return;
 			}
 			}
-			httpSession = (httpSession != null) ? httpSession : createNewSessionIfAllowed(context);
+			httpSession = (httpSession != null) ? httpSession : createNewSessionIfAllowed(context, authentication);
 			// If HttpSession exists, store current SecurityContext but only if it has
 			// If HttpSession exists, store current SecurityContext but only if it has
 			// actually changed in this thread (see SEC-37, SEC-1307, SEC-1528)
 			// actually changed in this thread (see SEC-37, SEC-1307, SEC-1528)
 			if (httpSession != null) {
 			if (httpSession != null) {
@@ -369,8 +369,8 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
 					|| context.getAuthentication() != this.authBeforeExecution;
 					|| context.getAuthentication() != this.authBeforeExecution;
 		}
 		}
 
 
-		private HttpSession createNewSessionIfAllowed(SecurityContext context) {
-			if (isTransientAuthentication(context.getAuthentication())) {
+		private HttpSession createNewSessionIfAllowed(SecurityContext context, Authentication authentication) {
+			if (isTransientAuthentication(authentication)) {
 				return null;
 				return null;
 			}
 			}
 			if (this.httpSessionExistedAtStartOfRequest) {
 			if (this.httpSessionExistedAtStartOfRequest) {

+ 17 - 1
web/src/test/java/org/springframework/security/web/context/HttpSessionSecurityContextRepositoryTests.java

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2021 the original author or authors.
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -628,6 +628,22 @@ public class HttpSessionSecurityContextRepositoryTests {
 		assertThat(session).isNull();
 		assertThat(session).isNull();
 	}
 	}
 
 
+	// gh-8947
+	@Test
+	public void saveContextWhenSecurityContextAuthenticationUpdatedToNullThenSkipped() {
+		HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
+		MockHttpServletRequest request = new MockHttpServletRequest();
+		MockHttpServletResponse response = new MockHttpServletResponse();
+		HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
+		SomeOtherTransientAuthentication authentication = new SomeOtherTransientAuthentication();
+		repo.loadContext(holder);
+		SecurityContext context = mock(SecurityContext.class);
+		given(context.getAuthentication()).willReturn(authentication).willReturn(null);
+		repo.saveContext(context, holder.getRequest(), holder.getResponse());
+		MockHttpSession session = (MockHttpSession) request.getSession(false);
+		assertThat(session).isNull();
+	}
+
 	private SecurityContext createSecurityContext(UserDetails userDetails) {
 	private SecurityContext createSecurityContext(UserDetails userDetails) {
 		UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userDetails,
 		UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userDetails,
 				userDetails.getPassword(), userDetails.getAuthorities());
 				userDetails.getPassword(), userDetails.getAuthorities());