Remove individual detection of forwarded headers
This commit removes all places where forwarded headers are checked implicitly, on an ad-hoc basis. ForwardedHeaderFilter is expected to be used instead providing centralized control over using or discarding such headers. Issue: SPR-16668
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,15 +16,19 @@
|
||||
|
||||
package org.springframework.web.cors.reactive;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.mock.web.test.server.MockServerWebExchange;
|
||||
import org.springframework.web.filter.reactive.ForwardedHeaderFilter;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.get;
|
||||
import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.options;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.*;
|
||||
|
||||
/**
|
||||
* Test case for reactive {@link CorsUtils}.
|
||||
@@ -35,19 +39,19 @@ public class CorsUtilsTests {
|
||||
|
||||
@Test
|
||||
public void isCorsRequest() {
|
||||
MockServerHttpRequest request = get("/").header(HttpHeaders.ORIGIN, "http://domain.com").build();
|
||||
ServerHttpRequest request = get("/").header(HttpHeaders.ORIGIN, "http://domain.com").build();
|
||||
assertTrue(CorsUtils.isCorsRequest(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNotCorsRequest() {
|
||||
MockServerHttpRequest request = get("/").build();
|
||||
ServerHttpRequest request = get("/").build();
|
||||
assertFalse(CorsUtils.isCorsRequest(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isPreFlightRequest() {
|
||||
MockServerHttpRequest request = options("/")
|
||||
ServerHttpRequest request = options("/")
|
||||
.header(HttpHeaders.ORIGIN, "http://domain.com")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET")
|
||||
.build();
|
||||
@@ -56,7 +60,7 @@ public class CorsUtilsTests {
|
||||
|
||||
@Test
|
||||
public void isNotPreFlightRequest() {
|
||||
MockServerHttpRequest request = get("/").build();
|
||||
ServerHttpRequest request = get("/").build();
|
||||
assertFalse(CorsUtils.isPreFlightRequest(request));
|
||||
|
||||
request = options("/").header(HttpHeaders.ORIGIN, "http://domain.com").build();
|
||||
@@ -68,31 +72,35 @@ public class CorsUtilsTests {
|
||||
|
||||
@Test // SPR-16262
|
||||
public void isSameOriginWithXForwardedHeaders() {
|
||||
assertTrue(checkSameOriginWithXForwardedHeaders("mydomain1.com", -1, "https", null, -1, "https://mydomain1.com"));
|
||||
assertTrue(checkSameOriginWithXForwardedHeaders("mydomain1.com", 123, "https", null, -1, "https://mydomain1.com"));
|
||||
assertTrue(checkSameOriginWithXForwardedHeaders("mydomain1.com", -1, "https", "mydomain2.com", -1, "https://mydomain2.com"));
|
||||
assertTrue(checkSameOriginWithXForwardedHeaders("mydomain1.com", 123, "https", "mydomain2.com", -1, "https://mydomain2.com"));
|
||||
assertTrue(checkSameOriginWithXForwardedHeaders("mydomain1.com", -1, "https", "mydomain2.com", 456, "https://mydomain2.com:456"));
|
||||
assertTrue(checkSameOriginWithXForwardedHeaders("mydomain1.com", 123, "https", "mydomain2.com", 456, "https://mydomain2.com:456"));
|
||||
String server = "mydomain1.com";
|
||||
testWithXForwardedHeaders(server, -1, "https", null, -1, "https://mydomain1.com");
|
||||
testWithXForwardedHeaders(server, 123, "https", null, -1, "https://mydomain1.com");
|
||||
testWithXForwardedHeaders(server, -1, "https", "mydomain2.com", -1, "https://mydomain2.com");
|
||||
testWithXForwardedHeaders(server, 123, "https", "mydomain2.com", -1, "https://mydomain2.com");
|
||||
testWithXForwardedHeaders(server, -1, "https", "mydomain2.com", 456, "https://mydomain2.com:456");
|
||||
testWithXForwardedHeaders(server, 123, "https", "mydomain2.com", 456, "https://mydomain2.com:456");
|
||||
}
|
||||
|
||||
@Test // SPR-16262
|
||||
public void isSameOriginWithForwardedHeader() {
|
||||
assertTrue(checkSameOriginWithForwardedHeader("mydomain1.com", -1, "proto=https", "https://mydomain1.com"));
|
||||
assertTrue(checkSameOriginWithForwardedHeader("mydomain1.com", 123, "proto=https", "https://mydomain1.com"));
|
||||
assertTrue(checkSameOriginWithForwardedHeader("mydomain1.com", -1, "proto=https; host=mydomain2.com", "https://mydomain2.com"));
|
||||
assertTrue(checkSameOriginWithForwardedHeader("mydomain1.com", 123, "proto=https; host=mydomain2.com", "https://mydomain2.com"));
|
||||
assertTrue(checkSameOriginWithForwardedHeader("mydomain1.com", -1, "proto=https; host=mydomain2.com:456", "https://mydomain2.com:456"));
|
||||
assertTrue(checkSameOriginWithForwardedHeader("mydomain1.com", 123, "proto=https; host=mydomain2.com:456", "https://mydomain2.com:456"));
|
||||
String server = "mydomain1.com";
|
||||
testWithForwardedHeader(server, -1, "proto=https", "https://mydomain1.com");
|
||||
testWithForwardedHeader(server, 123, "proto=https", "https://mydomain1.com");
|
||||
testWithForwardedHeader(server, -1, "proto=https; host=mydomain2.com", "https://mydomain2.com");
|
||||
testWithForwardedHeader(server, 123, "proto=https; host=mydomain2.com", "https://mydomain2.com");
|
||||
testWithForwardedHeader(server, -1, "proto=https; host=mydomain2.com:456", "https://mydomain2.com:456");
|
||||
testWithForwardedHeader(server, 123, "proto=https; host=mydomain2.com:456", "https://mydomain2.com:456");
|
||||
}
|
||||
|
||||
private boolean checkSameOriginWithXForwardedHeaders(String serverName, int port, String forwardedProto, String forwardedHost, int forwardedPort, String originHeader) {
|
||||
private void testWithXForwardedHeaders(String serverName, int port,
|
||||
String forwardedProto, String forwardedHost, int forwardedPort, String originHeader) {
|
||||
|
||||
String url = "http://" + serverName;
|
||||
if (port != -1) {
|
||||
url = url + ":" + port;
|
||||
}
|
||||
MockServerHttpRequest.BaseBuilder<?> builder = get(url)
|
||||
.header(HttpHeaders.ORIGIN, originHeader);
|
||||
|
||||
MockServerHttpRequest.BaseBuilder<?> builder = get(url).header(HttpHeaders.ORIGIN, originHeader);
|
||||
if (forwardedProto != null) {
|
||||
builder.header("X-Forwarded-Proto", forwardedProto);
|
||||
}
|
||||
@@ -102,18 +110,36 @@ public class CorsUtilsTests {
|
||||
if (forwardedPort != -1) {
|
||||
builder.header("X-Forwarded-Port", String.valueOf(forwardedPort));
|
||||
}
|
||||
return CorsUtils.isSameOrigin(builder.build());
|
||||
|
||||
ServerHttpRequest request = adaptFromForwardedHeaders(builder);
|
||||
assertTrue(CorsUtils.isSameOrigin(request));
|
||||
}
|
||||
|
||||
private boolean checkSameOriginWithForwardedHeader(String serverName, int port, String forwardedHeader, String originHeader) {
|
||||
private void testWithForwardedHeader(String serverName, int port,
|
||||
String forwardedHeader, String originHeader) {
|
||||
|
||||
String url = "http://" + serverName;
|
||||
if (port != -1) {
|
||||
url = url + ":" + port;
|
||||
}
|
||||
|
||||
MockServerHttpRequest.BaseBuilder<?> builder = get(url)
|
||||
.header("Forwarded", forwardedHeader)
|
||||
.header(HttpHeaders.ORIGIN, originHeader);
|
||||
return CorsUtils.isSameOrigin(builder.build());
|
||||
|
||||
ServerHttpRequest request = adaptFromForwardedHeaders(builder);
|
||||
assertTrue(CorsUtils.isSameOrigin(request));
|
||||
}
|
||||
|
||||
// SPR-16668
|
||||
private ServerHttpRequest adaptFromForwardedHeaders(MockServerHttpRequest.BaseBuilder<?> builder) {
|
||||
AtomicReference<ServerHttpRequest> requestRef = new AtomicReference<>();
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(builder);
|
||||
new ForwardedHeaderFilter().filter(exchange, exchange2 -> {
|
||||
requestRef.set(exchange2.getRequest());
|
||||
return Mono.empty();
|
||||
}).block();
|
||||
return requestRef.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,19 +21,20 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
import org.springframework.mock.web.test.MockFilterChain;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockHttpServletResponse;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.filter.ForwardedHeaderFilter;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
@@ -141,23 +142,25 @@ public class WebUtilsTests {
|
||||
}
|
||||
|
||||
@Test // SPR-16262
|
||||
public void isSameOriginWithXForwardedHeaders() {
|
||||
assertTrue(checkSameOriginWithXForwardedHeaders("mydomain1.com", -1, "https", null, -1, "https://mydomain1.com"));
|
||||
assertTrue(checkSameOriginWithXForwardedHeaders("mydomain1.com", 123, "https", null, -1, "https://mydomain1.com"));
|
||||
assertTrue(checkSameOriginWithXForwardedHeaders("mydomain1.com", -1, "https", "mydomain2.com", -1, "https://mydomain2.com"));
|
||||
assertTrue(checkSameOriginWithXForwardedHeaders("mydomain1.com", 123, "https", "mydomain2.com", -1, "https://mydomain2.com"));
|
||||
assertTrue(checkSameOriginWithXForwardedHeaders("mydomain1.com", -1, "https", "mydomain2.com", 456, "https://mydomain2.com:456"));
|
||||
assertTrue(checkSameOriginWithXForwardedHeaders("mydomain1.com", 123, "https", "mydomain2.com", 456, "https://mydomain2.com:456"));
|
||||
public void isSameOriginWithXForwardedHeaders() throws Exception {
|
||||
String server = "mydomain1.com";
|
||||
testWithXForwardedHeaders(server, -1, "https", null, -1, "https://mydomain1.com");
|
||||
testWithXForwardedHeaders(server, 123, "https", null, -1, "https://mydomain1.com");
|
||||
testWithXForwardedHeaders(server, -1, "https", "mydomain2.com", -1, "https://mydomain2.com");
|
||||
testWithXForwardedHeaders(server, 123, "https", "mydomain2.com", -1, "https://mydomain2.com");
|
||||
testWithXForwardedHeaders(server, -1, "https", "mydomain2.com", 456, "https://mydomain2.com:456");
|
||||
testWithXForwardedHeaders(server, 123, "https", "mydomain2.com", 456, "https://mydomain2.com:456");
|
||||
}
|
||||
|
||||
@Test // SPR-16262
|
||||
public void isSameOriginWithForwardedHeader() {
|
||||
assertTrue(checkSameOriginWithForwardedHeader("mydomain1.com", -1, "proto=https", "https://mydomain1.com"));
|
||||
assertTrue(checkSameOriginWithForwardedHeader("mydomain1.com", 123, "proto=https", "https://mydomain1.com"));
|
||||
assertTrue(checkSameOriginWithForwardedHeader("mydomain1.com", -1, "proto=https; host=mydomain2.com", "https://mydomain2.com"));
|
||||
assertTrue(checkSameOriginWithForwardedHeader("mydomain1.com", 123, "proto=https; host=mydomain2.com", "https://mydomain2.com"));
|
||||
assertTrue(checkSameOriginWithForwardedHeader("mydomain1.com", -1, "proto=https; host=mydomain2.com:456", "https://mydomain2.com:456"));
|
||||
assertTrue(checkSameOriginWithForwardedHeader("mydomain1.com", 123, "proto=https; host=mydomain2.com:456", "https://mydomain2.com:456"));
|
||||
public void isSameOriginWithForwardedHeader() throws Exception {
|
||||
String server = "mydomain1.com";
|
||||
testWithForwardedHeader(server, -1, "proto=https", "https://mydomain1.com");
|
||||
testWithForwardedHeader(server, 123, "proto=https", "https://mydomain1.com");
|
||||
testWithForwardedHeader(server, -1, "proto=https; host=mydomain2.com", "https://mydomain2.com");
|
||||
testWithForwardedHeader(server, 123, "proto=https; host=mydomain2.com", "https://mydomain2.com");
|
||||
testWithForwardedHeader(server, -1, "proto=https; host=mydomain2.com:456", "https://mydomain2.com:456");
|
||||
testWithForwardedHeader(server, 123, "proto=https; host=mydomain2.com:456", "https://mydomain2.com:456");
|
||||
}
|
||||
|
||||
|
||||
@@ -183,36 +186,53 @@ public class WebUtilsTests {
|
||||
return WebUtils.isSameOrigin(request);
|
||||
}
|
||||
|
||||
private boolean checkSameOriginWithXForwardedHeaders(String serverName, int port, String forwardedProto, String forwardedHost, int forwardedPort, String originHeader) {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest();
|
||||
ServerHttpRequest request = new ServletServerHttpRequest(servletRequest);
|
||||
servletRequest.setServerName(serverName);
|
||||
private void testWithXForwardedHeaders(String serverName, int port, String forwardedProto,
|
||||
String forwardedHost, int forwardedPort, String originHeader) throws Exception {
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setServerName(serverName);
|
||||
if (port != -1) {
|
||||
servletRequest.setServerPort(port);
|
||||
request.setServerPort(port);
|
||||
}
|
||||
if (forwardedProto != null) {
|
||||
servletRequest.addHeader("X-Forwarded-Proto", forwardedProto);
|
||||
request.addHeader("X-Forwarded-Proto", forwardedProto);
|
||||
}
|
||||
if (forwardedHost != null) {
|
||||
servletRequest.addHeader("X-Forwarded-Host", forwardedHost);
|
||||
request.addHeader("X-Forwarded-Host", forwardedHost);
|
||||
}
|
||||
if (forwardedPort != -1) {
|
||||
servletRequest.addHeader("X-Forwarded-Port", String.valueOf(forwardedPort));
|
||||
request.addHeader("X-Forwarded-Port", String.valueOf(forwardedPort));
|
||||
}
|
||||
servletRequest.addHeader(HttpHeaders.ORIGIN, originHeader);
|
||||
return WebUtils.isSameOrigin(request);
|
||||
request.addHeader(HttpHeaders.ORIGIN, originHeader);
|
||||
|
||||
HttpServletRequest requestToUse = adaptFromForwardedHeaders(request);
|
||||
ServerHttpRequest httpRequest = new ServletServerHttpRequest(requestToUse);
|
||||
|
||||
assertTrue(WebUtils.isSameOrigin(httpRequest));
|
||||
}
|
||||
|
||||
private boolean checkSameOriginWithForwardedHeader(String serverName, int port, String forwardedHeader, String originHeader) {
|
||||
MockHttpServletRequest servletRequest = new MockHttpServletRequest();
|
||||
ServerHttpRequest request = new ServletServerHttpRequest(servletRequest);
|
||||
servletRequest.setServerName(serverName);
|
||||
private void testWithForwardedHeader(String serverName, int port, String forwardedHeader,
|
||||
String originHeader) throws Exception {
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setServerName(serverName);
|
||||
if (port != -1) {
|
||||
servletRequest.setServerPort(port);
|
||||
request.setServerPort(port);
|
||||
}
|
||||
servletRequest.addHeader("Forwarded", forwardedHeader);
|
||||
servletRequest.addHeader(HttpHeaders.ORIGIN, originHeader);
|
||||
return WebUtils.isSameOrigin(request);
|
||||
request.addHeader("Forwarded", forwardedHeader);
|
||||
request.addHeader(HttpHeaders.ORIGIN, originHeader);
|
||||
|
||||
HttpServletRequest requestToUse = adaptFromForwardedHeaders(request);
|
||||
ServerHttpRequest httpRequest = new ServletServerHttpRequest(requestToUse);
|
||||
|
||||
assertTrue(WebUtils.isSameOrigin(httpRequest));
|
||||
}
|
||||
|
||||
// SPR-16668
|
||||
private HttpServletRequest adaptFromForwardedHeaders(HttpServletRequest request) throws Exception {
|
||||
MockFilterChain chain = new MockFilterChain();
|
||||
new ForwardedHeaderFilter().doFilter(request, new MockHttpServletResponse(), chain);
|
||||
return (HttpServletRequest) chain.getRequest();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user