Bläddra i källkod

Add SecurityContextHolderStrategy to new repository

In 6.0, RequestAttributeSecurityContextRepository will be the default
implementation of SecurityContextRepository. This commit adds the
ability to configure a custom SecurityContextHolderStrategy, similar
to other components.

Issue gh-11060
Closes gh-11895
Steve Riesenberg 2 år sedan
förälder
incheckning
5d757919a2

+ 16 - 1
web/src/main/java/org/springframework/security/web/context/RequestAttributeSecurityContextRepository.java

@@ -23,6 +23,8 @@ import javax.servlet.http.HttpServletResponse;
 
 import org.springframework.security.core.context.SecurityContext;
 import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.context.SecurityContextHolderStrategy;
+import org.springframework.util.Assert;
 
 /**
  * Stores the {@link SecurityContext} on a
@@ -48,6 +50,9 @@ public final class RequestAttributeSecurityContextRepository implements Security
 
 	private final String requestAttributeName;
 
+	private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
+			.getContextHolderStrategy();
+
 	/**
 	 * Creates a new instance using {@link #DEFAULT_REQUEST_ATTR_NAME}.
 	 */
@@ -81,7 +86,7 @@ public final class RequestAttributeSecurityContextRepository implements Security
 
 	private SecurityContext getContextOrEmpty(HttpServletRequest request) {
 		SecurityContext context = getContext(request);
-		return (context != null) ? context : SecurityContextHolder.createEmptyContext();
+		return (context != null) ? context : this.securityContextHolderStrategy.createEmptyContext();
 	}
 
 	private SecurityContext getContext(HttpServletRequest request) {
@@ -93,4 +98,14 @@ public final class RequestAttributeSecurityContextRepository implements Security
 		request.setAttribute(this.requestAttributeName, context);
 	}
 
+	/**
+	 * Sets the {@link SecurityContextHolderStrategy} to use. The default action is to use
+	 * the {@link SecurityContextHolderStrategy} stored in {@link SecurityContextHolder}.
+	 * @since 5.8
+	 */
+	public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
+		Assert.notNull(securityContextHolderStrategy, "securityContextHolderStrategy cannot be null");
+		this.securityContextHolderStrategy = securityContextHolderStrategy;
+	}
+
 }

+ 27 - 0
web/src/test/java/org/springframework/security/web/context/RequestAttributeSecurityContextRepositoryTests.java

@@ -25,9 +25,15 @@ import org.springframework.mock.web.MockHttpServletResponse;
 import org.springframework.security.authentication.TestAuthentication;
 import org.springframework.security.core.context.SecurityContext;
 import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.context.SecurityContextHolderStrategy;
 import org.springframework.security.core.context.SecurityContextImpl;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
 
 /**
  * @author Rob Winch
@@ -42,6 +48,15 @@ class RequestAttributeSecurityContextRepositoryTests {
 
 	private SecurityContext expectedSecurityContext = new SecurityContextImpl(TestAuthentication.authenticatedUser());
 
+	@Test
+	void setSecurityContextHolderStrategyWhenNullThenThrowsIllegalArgumentException() {
+		// @formatter:off
+		assertThatIllegalArgumentException()
+				.isThrownBy(() -> this.repository.setSecurityContextHolderStrategy(null))
+				.withMessage("securityContextHolderStrategy cannot be null");
+		// @formatter:on
+	}
+
 	@Test
 	void saveContextAndLoadContextThenFound() {
 		this.repository.saveContext(this.expectedSecurityContext, this.request, this.response);
@@ -82,4 +97,16 @@ class RequestAttributeSecurityContextRepositoryTests {
 		assertThat(context).isEqualTo(SecurityContextHolder.createEmptyContext());
 	}
 
+	@Test
+	void loadContextWhenCustomSecurityContextHolderStrategySetThenUsed() {
+		SecurityContextHolderStrategy securityContextHolderStrategy = mock(SecurityContextHolderStrategy.class);
+		given(securityContextHolderStrategy.createEmptyContext()).willReturn(new SecurityContextImpl());
+		this.repository.setSecurityContextHolderStrategy(securityContextHolderStrategy);
+
+		Supplier<SecurityContext> deferredContext = this.repository.loadContext(this.request);
+		assertThat(deferredContext.get()).isNotNull();
+		verify(securityContextHolderStrategy).createEmptyContext();
+		verifyNoMoreInteractions(securityContextHolderStrategy);
+	}
+
 }