Skip to content

Commit

Permalink
Fix case sensitive headers comparison
Browse files Browse the repository at this point in the history
  • Loading branch information
sjohnr committed Dec 1, 2021
1 parent a17dfb8 commit 41c6776
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package org.springframework.security.web.server.header;

import java.util.Arrays;
import java.util.Collections;

import reactor.core.publisher.Mono;

Expand All @@ -41,8 +40,16 @@ public StaticServerHttpHeadersWriter(HttpHeaders headersToAdd) {
@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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@

package org.springframework.security.web.server.header;

import java.util.Locale;

import org.junit.jupiter.api.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;
Expand Down Expand Up @@ -56,6 +59,24 @@ public void writeHeadersWhenSingleHeaderAndHeaderWrittenThenSuccess() {
.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()
Expand Down

0 comments on commit 41c6776

Please sign in to comment.