Description
Describe the bug
Since spring-security 6.3.4 headers from firewalled requests from the new StrictServerWebExchangeFirewall
, which was added here, cannot be mutated.
The reason is:
A call to mutate()
on the exchange uses the DefaultServerHttpRequestBuilder
which initializes the headers
with a call to HttpHeaders.writableHttpHeaders(original.getHeaders())
.
And in HttpHeaders.writableHttpHeaders
new HttpHeaders
are created if there are ReadOnlyHttpHeaders
.
But the StrictServerWebExchangeFirewall
wraps the original headers with the delegate class StrictFirewallHttpHeaders
. Thus, those headers are not ReadOnlyHttpHeaders
anymore.
To Reproduce
See sample below.
Expected behavior
The headers can be mutated, after calling mutate()
even for firewalled requests.
Sample
Testcase:
package com.exmple.securityreadonlyheaders;
import org.junit.jupiter.api.Test;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.security.web.server.firewall.StrictServerWebExchangeFirewall;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
class SecurityReadonlyHeadersApplicationTests {
@Test
void firewalledExchange() {
final var exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/test").build());
var firewall = new StrictServerWebExchangeFirewall();
var firewalledExchange = firewall.getFirewalledExchange(exchange).block();
assertDoesNotThrow(() -> firewalledExchange.mutate()
.request(r -> r.headers(h -> h.set("Content-Type", "application/json"))));
}
}