瀏覽代碼

Configure ContentNegotiationStrategy in HttpSecurityConfiguration

Closes gh-11916
Marcus Da Coregio 2 年之前
父節點
當前提交
cf3349f31a

+ 10 - 0
config/src/main/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.java

@@ -38,6 +38,8 @@ import org.springframework.security.config.annotation.web.configurers.DefaultLog
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.core.context.SecurityContextHolderStrategy;
 import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter;
+import org.springframework.web.accept.ContentNegotiationStrategy;
+import org.springframework.web.accept.HeaderContentNegotiationStrategy;
 
 import static org.springframework.security.config.Customizer.withDefaults;
 
@@ -65,6 +67,8 @@ class HttpSecurityConfiguration {
 	private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
 			.getContextHolderStrategy();
 
+	private ContentNegotiationStrategy contentNegotiationStrategy = new HeaderContentNegotiationStrategy();
+
 	@Autowired
 	void setObjectPostProcessor(ObjectPostProcessor<Object> objectPostProcessor) {
 		this.objectPostProcessor = objectPostProcessor;
@@ -89,6 +93,11 @@ class HttpSecurityConfiguration {
 		this.securityContextHolderStrategy = securityContextHolderStrategy;
 	}
 
+	@Autowired(required = false)
+	void setContentNegotiationStrategy(ContentNegotiationStrategy contentNegotiationStrategy) {
+		this.contentNegotiationStrategy = contentNegotiationStrategy;
+	}
+
 	@Bean(HTTPSECURITY_BEAN_NAME)
 	@Scope("prototype")
 	HttpSecurity httpSecurity() throws Exception {
@@ -143,6 +152,7 @@ class HttpSecurityConfiguration {
 	private Map<Class<?>, Object> createSharedObjects() {
 		Map<Class<?>, Object> sharedObjects = new HashMap<>();
 		sharedObjects.put(ApplicationContext.class, this.context);
+		sharedObjects.put(ContentNegotiationStrategy.class, this.contentNegotiationStrategy);
 		return sharedObjects;
 	}
 

+ 36 - 0
config/src/test/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfigurationTests.java

@@ -60,12 +60,16 @@ import org.springframework.security.web.header.writers.frameoptions.XFrameOption
 import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.MvcResult;
 import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
+import org.springframework.web.accept.ContentNegotiationStrategy;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.context.request.NativeWebRequest;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.springframework.security.config.Customizer.withDefaults;
 import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
@@ -311,6 +315,14 @@ public class HttpSecurityConfigurationTests {
 		assertThat(configurer.configure).isTrue();
 	}
 
+	@Test
+	public void getWhenCustomContentNegotiationStrategyThenUses() throws Exception {
+		this.spring.register(CustomContentNegotiationStrategyConfig.class).autowire();
+		this.mockMvc.perform(get("/"));
+		verify(CustomContentNegotiationStrategyConfig.CNS, atLeastOnce())
+				.resolveMediaTypes(any(NativeWebRequest.class));
+	}
+
 	@RestController
 	static class NameController {
 
@@ -489,6 +501,30 @@ public class HttpSecurityConfigurationTests {
 
 	}
 
+	@Configuration
+	@EnableWebSecurity
+	static class CustomContentNegotiationStrategyConfig {
+
+		@Bean
+		SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
+			// @formatter:off
+			http
+					.authorizeHttpRequests((requests) -> requests
+							.anyRequest().authenticated()
+					);
+			// @formatter:on
+			return http.build();
+		}
+
+		static ContentNegotiationStrategy CNS = mock(ContentNegotiationStrategy.class);
+
+		@Bean
+		static ContentNegotiationStrategy cns() {
+			return CNS;
+		}
+
+	}
+
 	static class DefaultConfigurer extends AbstractHttpConfigurer<DefaultConfigurer, HttpSecurity> {
 
 		boolean init;