2
0
Эх сурвалжийг харах

Fix case sensitive headers comparison

Closes gh-10557
Steve Riesenberg 3 жил өмнө
parent
commit
414e096ae4

+ 10 - 3
web/src/main/java/org/springframework/security/web/server/header/StaticServerHttpHeadersWriter.java

@@ -17,7 +17,6 @@
 package org.springframework.security.web.server.header;
 
 import java.util.Arrays;
-import java.util.Collections;
 
 import reactor.core.publisher.Mono;
 
@@ -41,8 +40,16 @@ public class StaticServerHttpHeadersWriter implements ServerHttpHeadersWriter {
 	@Override
 	public Mono<Void> writeHttpHeaders(ServerWebExchange exchange) {
 		HttpHeaders headers = exchange.getResponse().getHeaders();
-		boolean containsOneHeaderToAdd = Collections.disjoint(headers.keySet(), this.headersToAdd.keySet());
-		if (containsOneHeaderToAdd) {
+		// Note: We need to ensure that the following algorithm compares headers
+		// case insensitively, which should be true of headers.containsKey().
+		boolean containsNoHeadersToAdd = true;
+		for (String headerName : this.headersToAdd.keySet()) {
+			if (headers.containsKey(headerName)) {
+				containsNoHeadersToAdd = false;
+				break;
+			}
+		}
+		if (containsNoHeadersToAdd) {
 			this.headersToAdd.forEach(headers::put);
 		}
 		return Mono.empty();

+ 21 - 0
web/src/test/java/org/springframework/security/web/server/header/StaticServerHttpHeadersWriterTests.java

@@ -16,11 +16,14 @@
 
 package org.springframework.security.web.server.header;
 
+import java.util.Locale;
+
 import org.junit.Test;
 
 import org.springframework.http.HttpHeaders;
 import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
 import org.springframework.mock.web.server.MockServerWebExchange;
+import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.web.server.ServerWebExchange;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -56,6 +59,24 @@ public class StaticServerHttpHeadersWriterTests {
 				.containsOnly(headerValue);
 	}
 
+	// gh-10557
+	@Test
+	public void writeHeadersWhenHeaderWrittenWithDifferentCaseThenDoesNotWriteHeaders() {
+		String headerName = HttpHeaders.CACHE_CONTROL.toLowerCase(Locale.ROOT);
+		String headerValue = "max-age=120";
+		this.headers.set(headerName, headerValue);
+		// Note: This test inverts which collection uses case sensitive headers,
+		// due to the fact that gh-10557 reports NettyHeadersAdapter as the
+		// response headers implementation, which is not accessible here.
+		HttpHeaders caseSensitiveHeaders = new HttpHeaders(new LinkedMultiValueMap<>());
+		caseSensitiveHeaders.set(HttpHeaders.CACHE_CONTROL, CacheControlServerHttpHeadersWriter.CACHE_CONTRTOL_VALUE);
+		caseSensitiveHeaders.set(HttpHeaders.PRAGMA, CacheControlServerHttpHeadersWriter.PRAGMA_VALUE);
+		caseSensitiveHeaders.set(HttpHeaders.EXPIRES, CacheControlServerHttpHeadersWriter.EXPIRES_VALUE);
+		this.writer = new StaticServerHttpHeadersWriter(caseSensitiveHeaders);
+		this.writer.writeHttpHeaders(this.exchange);
+		assertThat(this.headers.get(headerName)).containsOnly(headerValue);
+	}
+
 	@Test
 	public void writeHeadersWhenMultiHeaderThenWritesAllHeaders() {
 		this.writer = StaticServerHttpHeadersWriter.builder()