CORS: Allowed to configure allow-credentials header to work via SSL
This adds support to return the "Access-Control-Allow-Credentials" header if needed, so CORS will work flawlessly with authenticated applications. Closes #6380
This commit is contained in:
parent
657b954528
commit
35e67c84fa
|
@ -57,6 +57,10 @@ be cached for. Defaults to `1728000` (20 days)
|
||||||
|`http.cors.allow-headers` |Which headers to allow. Defaults to
|
|`http.cors.allow-headers` |Which headers to allow. Defaults to
|
||||||
`X-Requested-With, Content-Type, Content-Length`.
|
`X-Requested-With, Content-Type, Content-Length`.
|
||||||
|
|
||||||
|
|`http.cors.allow-credentials` | Whether the `Access-Control-Allow-Credentials`
|
||||||
|
header should be returned. Note: This header is only returned, when the setting is
|
||||||
|
set to `true`. Defaults to `false`
|
||||||
|
|
||||||
|
|
||||||
|=======================================================================
|
|=======================================================================
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import static org.elasticsearch.http.netty.NettyHttpServerTransport.*;
|
||||||
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
|
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,20 +98,24 @@ public class NettyHttpChannel extends HttpChannel {
|
||||||
resp = new DefaultHttpResponse(HttpVersion.HTTP_1_1, status);
|
resp = new DefaultHttpResponse(HttpVersion.HTTP_1_1, status);
|
||||||
}
|
}
|
||||||
if (RestUtils.isBrowser(nettyRequest.headers().get(USER_AGENT))) {
|
if (RestUtils.isBrowser(nettyRequest.headers().get(USER_AGENT))) {
|
||||||
if (transport.settings().getAsBoolean("http.cors.enabled", true)) {
|
if (transport.settings().getAsBoolean(SETTING_CORS_ENABLED, true)) {
|
||||||
String originHeader = request.header(ORIGIN);
|
String originHeader = request.header(ORIGIN);
|
||||||
if (!Strings.isNullOrEmpty(originHeader)) {
|
if (!Strings.isNullOrEmpty(originHeader)) {
|
||||||
if (corsPattern == null) {
|
if (corsPattern == null) {
|
||||||
resp.headers().add(ACCESS_CONTROL_ALLOW_ORIGIN, transport.settings().get("http.cors.allow-origin", "*"));
|
resp.headers().add(ACCESS_CONTROL_ALLOW_ORIGIN, transport.settings().get(SETTING_CORS_ALLOW_ORIGIN, "*"));
|
||||||
} else {
|
} else {
|
||||||
resp.headers().add(ACCESS_CONTROL_ALLOW_ORIGIN, corsPattern.matcher(originHeader).matches() ? originHeader : "null");
|
resp.headers().add(ACCESS_CONTROL_ALLOW_ORIGIN, corsPattern.matcher(originHeader).matches() ? originHeader : "null");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nettyRequest.getMethod() == HttpMethod.OPTIONS) {
|
if (nettyRequest.getMethod() == HttpMethod.OPTIONS) {
|
||||||
// Allow Ajax requests based on the CORS "preflight" request
|
// Allow Ajax requests based on the CORS "preflight" request
|
||||||
resp.headers().add(ACCESS_CONTROL_MAX_AGE, transport.settings().getAsInt("http.cors.max-age", 1728000));
|
resp.headers().add(ACCESS_CONTROL_MAX_AGE, transport.settings().getAsInt(SETTING_CORS_MAX_AGE, 1728000));
|
||||||
resp.headers().add(ACCESS_CONTROL_ALLOW_METHODS, transport.settings().get("http.cors.allow-methods", "OPTIONS, HEAD, GET, POST, PUT, DELETE"));
|
resp.headers().add(ACCESS_CONTROL_ALLOW_METHODS, transport.settings().get(SETTING_CORS_ALLOW_METHODS, "OPTIONS, HEAD, GET, POST, PUT, DELETE"));
|
||||||
resp.headers().add(ACCESS_CONTROL_ALLOW_HEADERS, transport.settings().get("http.cors.allow-headers", "X-Requested-With, Content-Type, Content-Length"));
|
resp.headers().add(ACCESS_CONTROL_ALLOW_HEADERS, transport.settings().get(SETTING_CORS_ALLOW_HEADERS, "X-Requested-With, Content-Type, Content-Length"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transport.settings().getAsBoolean(SETTING_CORS_ALLOW_CREDENTIALS, false)) {
|
||||||
|
resp.headers().add(ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,13 @@ public class NettyHttpServerTransport extends AbstractLifecycleComponent<HttpSer
|
||||||
NettyUtils.setup();
|
NettyUtils.setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final String SETTING_CORS_ENABLED = "http.cors.enabled";
|
||||||
|
public static final String SETTING_CORS_ALLOW_ORIGIN = "http.cors.allow-origin";
|
||||||
|
public static final String SETTING_CORS_MAX_AGE = "http.cors.max-age";
|
||||||
|
public static final String SETTING_CORS_ALLOW_METHODS = "http.cors.allow-methods";
|
||||||
|
public static final String SETTING_CORS_ALLOW_HEADERS = "http.cors.allow-headers";
|
||||||
|
public static final String SETTING_CORS_ALLOW_CREDENTIALS = "http.cors.allow-credentials";
|
||||||
|
|
||||||
private final NetworkService networkService;
|
private final NetworkService networkService;
|
||||||
final BigArrays bigArrays;
|
final BigArrays bigArrays;
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ public class CorsRegexDefaultTests extends ElasticsearchIntegrationTest {
|
||||||
assertThat(response.getStatusCode(), is(200));
|
assertThat(response.getStatusCode(), is(200));
|
||||||
assertThat(response.getHeaders(), hasKey("Access-Control-Allow-Origin"));
|
assertThat(response.getHeaders(), hasKey("Access-Control-Allow-Origin"));
|
||||||
assertThat(response.getHeaders().get("Access-Control-Allow-Origin"), is("*"));
|
assertThat(response.getHeaders().get("Access-Control-Allow-Origin"), is("*"));
|
||||||
|
assertThat(response.getHeaders(), not(hasKey("Access-Control-Allow-Credentials")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -46,5 +47,6 @@ public class CorsRegexDefaultTests extends ElasticsearchIntegrationTest {
|
||||||
|
|
||||||
assertThat(response.getStatusCode(), is(200));
|
assertThat(response.getStatusCode(), is(200));
|
||||||
assertThat(response.getHeaders(), not(hasKey("Access-Control-Allow-Origin")));
|
assertThat(response.getHeaders(), not(hasKey("Access-Control-Allow-Origin")));
|
||||||
|
assertThat(response.getHeaders(), not(hasKey("Access-Control-Allow-Credentials")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,12 @@ import org.junit.Test;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
|
||||||
|
import static org.elasticsearch.http.netty.NettyHttpServerTransport.SETTING_CORS_ALLOW_ORIGIN;
|
||||||
|
import static org.elasticsearch.http.netty.NettyHttpServerTransport.SETTING_CORS_ALLOW_CREDENTIALS;
|
||||||
import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
|
import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
|
||||||
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope;
|
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -47,8 +50,8 @@ public class CorsRegexTests extends ElasticsearchIntegrationTest {
|
||||||
@Override
|
@Override
|
||||||
protected Settings nodeSettings(int nodeOrdinal) {
|
protected Settings nodeSettings(int nodeOrdinal) {
|
||||||
return ImmutableSettings.settingsBuilder()
|
return ImmutableSettings.settingsBuilder()
|
||||||
.put("http.cors.allow-origin", "/https?:\\/\\/localhost(:[0-9]+)?/")
|
.put(SETTING_CORS_ALLOW_ORIGIN, "/https?:\\/\\/localhost(:[0-9]+)?/")
|
||||||
.put("network.host", "127.0.0.1")
|
.put(SETTING_CORS_ALLOW_CREDENTIALS, "true")
|
||||||
.put(super.nodeSettings(nodeOrdinal))
|
.put(super.nodeSettings(nodeOrdinal))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
@ -62,6 +65,8 @@ public class CorsRegexTests extends ElasticsearchIntegrationTest {
|
||||||
corsValue = "https://localhost:9200";
|
corsValue = "https://localhost:9200";
|
||||||
response = httpClient().method("GET").path("/").addHeader("User-Agent", "Mozilla Bar").addHeader("Origin", corsValue).execute();
|
response = httpClient().method("GET").path("/").addHeader("User-Agent", "Mozilla Bar").addHeader("Origin", corsValue).execute();
|
||||||
assertResponseWithOriginheader(response, corsValue);
|
assertResponseWithOriginheader(response, corsValue);
|
||||||
|
assertThat(response.getHeaders(), hasKey("Access-Control-Allow-Credentials"));
|
||||||
|
assertThat(response.getHeaders().get("Access-Control-Allow-Credentials"), is("true"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue