浏览代码

Fix case sensitive headers comparison

Closes gh-10557
Steve Riesenberg 3 年之前
父节点
当前提交
3aa2a60f97

+ 11 - 6
web/src/main/java/org/springframework/security/web/server/header/StaticServerHttpHeadersWriter.java

@@ -16,7 +16,6 @@
 package org.springframework.security.web.server.header;
 
 import java.util.Arrays;
-import java.util.Collections;
 
 import org.springframework.http.HttpHeaders;
 import org.springframework.web.server.ServerWebExchange;
@@ -42,11 +41,17 @@ 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) {
-			this.headersToAdd.forEach((name, values) -> {
-				headers.put(name, values);
-			});
+		// 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

@@ -17,10 +17,13 @@ package org.springframework.security.web.server.header;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
+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;
 
 /**
@@ -56,6 +59,24 @@ public class StaticServerHttpHeadersWriterTests {
 		assertThat(headers.get(ContentTypeOptionsServerHttpHeadersWriter.X_CONTENT_OPTIONS)).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() {
 		writer = StaticServerHttpHeadersWriter.builder()