Bläddra i källkod

Address SecurityContextHolder memory leak

To get current context without creating a new context.
Creating a new context may cause ThreadLocal leak.

Closes gh-9841
Hiroshi Shirosaki 4 år sedan
förälder
incheckning
2bc643d6c8

+ 12 - 2
config/src/main/java/org/springframework/security/config/annotation/web/configuration/SecurityReactorContextConfiguration.java

@@ -36,6 +36,7 @@ import org.springframework.beans.factory.InitializingBean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContext;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.web.context.request.RequestAttributes;
 import org.springframework.web.context.request.RequestContextHolder;
@@ -94,7 +95,12 @@ class SecurityReactorContextConfiguration {
 		}
 
 		private static boolean contextAttributesAvailable() {
-			return SecurityContextHolder.getContext().getAuthentication() != null
+			SecurityContext context = SecurityContextHolder.peekContext();
+			Authentication authentication = null;
+			if (context != null) {
+				authentication = context.getAuthentication();
+			}
+			return authentication != null
 					|| RequestContextHolder.getRequestAttributes() instanceof ServletRequestAttributes;
 		}
 
@@ -107,7 +113,11 @@ class SecurityReactorContextConfiguration {
 				servletRequest = servletRequestAttributes.getRequest();
 				servletResponse = servletRequestAttributes.getResponse(); // possible null
 			}
-			Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+			SecurityContext context = SecurityContextHolder.peekContext();
+			Authentication authentication = null;
+			if (context != null) {
+				authentication = context.getAuthentication();
+			}
 			if (authentication == null && servletRequest == null) {
 				return Collections.emptyMap();
 			}

+ 5 - 0
core/src/main/java/org/springframework/security/core/context/GlobalSecurityContextHolderStrategy.java

@@ -44,6 +44,11 @@ final class GlobalSecurityContextHolderStrategy implements SecurityContextHolder
 		return contextHolder;
 	}
 
+	@Override
+	public SecurityContext peekContext() {
+		return contextHolder;
+	}
+
 	@Override
 	public void setContext(SecurityContext context) {
 		Assert.notNull(context, "Only non-null SecurityContext instances are permitted");

+ 5 - 0
core/src/main/java/org/springframework/security/core/context/InheritableThreadLocalSecurityContextHolderStrategy.java

@@ -44,6 +44,11 @@ final class InheritableThreadLocalSecurityContextHolderStrategy implements Secur
 		return ctx;
 	}
 
+	@Override
+	public SecurityContext peekContext() {
+		return contextHolder.get();
+	}
+
 	@Override
 	public void setContext(SecurityContext context) {
 		Assert.notNull(context, "Only non-null SecurityContext instances are permitted");

+ 8 - 0
core/src/main/java/org/springframework/security/core/context/SecurityContextHolder.java

@@ -123,6 +123,14 @@ public class SecurityContextHolder {
 		return strategy.getContext();
 	}
 
+	/**
+	 * Peeks the current <code>SecurityContext</code>.
+	 * @return the security context (may be <code>null</code>)
+	 */
+	public static SecurityContext peekContext() {
+		return strategy.peekContext();
+	}
+
 	/**
 	 * Primarily for troubleshooting purposes, this method shows how many times the class
 	 * has re-initialized its <code>SecurityContextHolderStrategy</code>.

+ 6 - 0
core/src/main/java/org/springframework/security/core/context/SecurityContextHolderStrategy.java

@@ -38,6 +38,12 @@ public interface SecurityContextHolderStrategy {
 	 */
 	SecurityContext getContext();
 
+	/**
+	 * Peeks the current context without creating an empty context.
+	 * @return a context (may be <code>null</code>)
+	 */
+	SecurityContext peekContext();
+
 	/**
 	 * Sets the current context.
 	 * @param context to the new argument (should never be <code>null</code>, although

+ 5 - 0
core/src/main/java/org/springframework/security/core/context/ThreadLocalSecurityContextHolderStrategy.java

@@ -45,6 +45,11 @@ final class ThreadLocalSecurityContextHolderStrategy implements SecurityContextH
 		return ctx;
 	}
 
+	@Override
+	public SecurityContext peekContext() {
+		return contextHolder.get();
+	}
+
 	@Override
 	public void setContext(SecurityContext context) {
 		Assert.notNull(context, "Only non-null SecurityContext instances are permitted");