Add Cross Origin Policies headers
Add DSL support for Cross-Origin-Opener-Policy, Cross-Origin-Embedder-Policy and Cross-Origin-Resource-Policy headers Closes gh-9385, gh-10118
This commit is contained in:
committed by
Eleftheria Stein-Kousathana
parent
7ec3b55ab3
commit
65426a40ec
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -26,11 +26,16 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.test.SpringTestContext;
|
||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.header.writers.CrossOriginEmbedderPolicyHeaderWriter;
|
||||
import org.springframework.security.web.header.writers.CrossOriginOpenerPolicyHeaderWriter;
|
||||
import org.springframework.security.web.header.writers.CrossOriginResourcePolicyHeaderWriter;
|
||||
import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter.ReferrerPolicy;
|
||||
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter.XFrameOptionsMode;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
@@ -52,6 +57,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
* @author Eddú Meléndez
|
||||
* @author Vedran Pavic
|
||||
* @author Eleftheria Stein
|
||||
* @author Marcus Da Coregio
|
||||
*/
|
||||
@ExtendWith(SpringTestContextExtension.class)
|
||||
public class HeadersConfigurerTests {
|
||||
@@ -514,6 +520,30 @@ public class HeadersConfigurerTests {
|
||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.STRICT_TRANSPORT_SECURITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenCustomCrossOriginPoliciesInLambdaThenCrossOriginPolicyHeadersWithCustomValuesInResponse()
|
||||
throws Exception {
|
||||
this.spring.register(CrossOriginCustomPoliciesInLambdaConfig.class).autowire();
|
||||
MvcResult mvcResult = this.mvc.perform(get("/"))
|
||||
.andExpect(header().string(HttpHeaders.CROSS_ORIGIN_OPENER_POLICY, "same-origin"))
|
||||
.andExpect(header().string(HttpHeaders.CROSS_ORIGIN_EMBEDDER_POLICY, "require-corp"))
|
||||
.andExpect(header().string(HttpHeaders.CROSS_ORIGIN_RESOURCE_POLICY, "same-origin")).andReturn();
|
||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.CROSS_ORIGIN_OPENER_POLICY,
|
||||
HttpHeaders.CROSS_ORIGIN_EMBEDDER_POLICY, HttpHeaders.CROSS_ORIGIN_RESOURCE_POLICY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWhenCustomCrossOriginPoliciesThenCrossOriginPolicyHeadersWithCustomValuesInResponse()
|
||||
throws Exception {
|
||||
this.spring.register(CrossOriginCustomPoliciesConfig.class).autowire();
|
||||
MvcResult mvcResult = this.mvc.perform(get("/"))
|
||||
.andExpect(header().string(HttpHeaders.CROSS_ORIGIN_OPENER_POLICY, "same-origin"))
|
||||
.andExpect(header().string(HttpHeaders.CROSS_ORIGIN_EMBEDDER_POLICY, "require-corp"))
|
||||
.andExpect(header().string(HttpHeaders.CROSS_ORIGIN_RESOURCE_POLICY, "same-origin")).andReturn();
|
||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.CROSS_ORIGIN_OPENER_POLICY,
|
||||
HttpHeaders.CROSS_ORIGIN_EMBEDDER_POLICY, HttpHeaders.CROSS_ORIGIN_RESOURCE_POLICY);
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class HeadersConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@@ -1146,4 +1176,50 @@ public class HeadersConfigurerTests {
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class CrossOriginCustomPoliciesInLambdaConfig {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http.headers((headers) -> headers
|
||||
.defaultsDisabled()
|
||||
.crossOriginOpenerPolicy((policy) -> policy
|
||||
.policy(CrossOriginOpenerPolicyHeaderWriter.CrossOriginOpenerPolicy.SAME_ORIGIN)
|
||||
)
|
||||
.crossOriginEmbedderPolicy((policy) -> policy
|
||||
.policy(CrossOriginEmbedderPolicyHeaderWriter.CrossOriginEmbedderPolicy.REQUIRE_CORP)
|
||||
)
|
||||
.crossOriginResourcePolicy((policy) -> policy
|
||||
.policy(CrossOriginResourcePolicyHeaderWriter.CrossOriginResourcePolicy.SAME_ORIGIN)
|
||||
)
|
||||
);
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class CrossOriginCustomPoliciesConfig {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http.headers()
|
||||
.defaultsDisabled()
|
||||
.crossOriginOpenerPolicy()
|
||||
.policy(CrossOriginOpenerPolicyHeaderWriter.CrossOriginOpenerPolicy.SAME_ORIGIN)
|
||||
.and()
|
||||
.crossOriginEmbedderPolicy()
|
||||
.policy(CrossOriginEmbedderPolicyHeaderWriter.CrossOriginEmbedderPolicy.REQUIRE_CORP)
|
||||
.and()
|
||||
.crossOriginResourcePolicy()
|
||||
.policy(CrossOriginResourcePolicyHeaderWriter.CrossOriginResourcePolicy.SAME_ORIGIN);
|
||||
// @formatter:on
|
||||
return http.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -48,6 +48,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
* @author Tim Ysewyn
|
||||
* @author Josh Cummings
|
||||
* @author Rafiullah Hamedy
|
||||
* @author Marcus Da Coregio
|
||||
*/
|
||||
@ExtendWith(SpringTestContextExtension.class)
|
||||
public class HttpHeadersConfigTests {
|
||||
@@ -733,6 +734,53 @@ public class HttpHeadersConfigTests {
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenCrossOriginOpenerPolicyWithSameOriginAllowPopupsThenRespondsWithSameOriginAllowPopups()
|
||||
throws Exception {
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithCrossOriginOpenerPolicy")).autowire();
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(excludesDefaults())
|
||||
.andExpect(header().string("Cross-Origin-Opener-Policy", "same-origin-allow-popups"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenCrossOriginEmbedderPolicyWithRequireCorpThenRespondsWithRequireCorp() throws Exception {
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithCrossOriginEmbedderPolicy")).autowire();
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(excludesDefaults())
|
||||
.andExpect(header().string("Cross-Origin-Embedder-Policy", "require-corp"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenCrossOriginResourcePolicyWithSameOriginThenRespondsWithSameOrigin() throws Exception {
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithCrossOriginResourcePolicy")).autowire();
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(excludesDefaults())
|
||||
.andExpect(header().string("Cross-Origin-Resource-Policy", "same-origin"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenCrossOriginPoliciesRespondsCrossOriginPolicies() throws Exception {
|
||||
this.spring.configLocations(this.xml("DefaultsDisabledWithCrossOriginPolicies")).autowire();
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(excludesDefaults())
|
||||
.andExpect(header().string("Cross-Origin-Opener-Policy", "same-origin"))
|
||||
.andExpect(header().string("Cross-Origin-Embedder-Policy", "require-corp"))
|
||||
.andExpect(header().string("Cross-Origin-Resource-Policy", "same-origin"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static ResultMatcher includesDefaults() {
|
||||
return includes(defaultHeaders);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -30,6 +30,9 @@ import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.security.test.web.reactive.server.WebTestClientBuilder;
|
||||
import org.springframework.security.web.server.header.ContentSecurityPolicyServerHttpHeadersWriter;
|
||||
import org.springframework.security.web.server.header.ContentTypeOptionsServerHttpHeadersWriter;
|
||||
import org.springframework.security.web.server.header.CrossOriginEmbedderPolicyServerHttpHeadersWriter;
|
||||
import org.springframework.security.web.server.header.CrossOriginOpenerPolicyServerHttpHeadersWriter;
|
||||
import org.springframework.security.web.server.header.CrossOriginResourcePolicyServerHttpHeadersWriter;
|
||||
import org.springframework.security.web.server.header.FeaturePolicyServerHttpHeadersWriter;
|
||||
import org.springframework.security.web.server.header.ReferrerPolicyServerHttpHeadersWriter;
|
||||
import org.springframework.security.web.server.header.ReferrerPolicyServerHttpHeadersWriter.ReferrerPolicy;
|
||||
@@ -48,6 +51,7 @@ import static org.springframework.security.config.Customizer.withDefaults;
|
||||
* @author Rob Winch
|
||||
* @author Vedran Pavic
|
||||
* @author Ankur Pathak
|
||||
* @author Marcus Da Coregio
|
||||
* @since 5.0
|
||||
*/
|
||||
public class HeaderSpecTests {
|
||||
@@ -406,6 +410,53 @@ public class HeaderSpecTests {
|
||||
assertHeaders();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headersWhenCrossOriginPoliciesCustomEnabledThenCustomCrossOriginPoliciesWritten() {
|
||||
this.expectedHeaders.add(CrossOriginOpenerPolicyServerHttpHeadersWriter.OPENER_POLICY,
|
||||
CrossOriginOpenerPolicyServerHttpHeadersWriter.CrossOriginOpenerPolicy.SAME_ORIGIN_ALLOW_POPUPS
|
||||
.getPolicy());
|
||||
this.expectedHeaders.add(CrossOriginEmbedderPolicyServerHttpHeadersWriter.EMBEDDER_POLICY,
|
||||
CrossOriginEmbedderPolicyServerHttpHeadersWriter.CrossOriginEmbedderPolicy.REQUIRE_CORP.getPolicy());
|
||||
this.expectedHeaders.add(CrossOriginResourcePolicyServerHttpHeadersWriter.RESOURCE_POLICY,
|
||||
CrossOriginResourcePolicyServerHttpHeadersWriter.CrossOriginResourcePolicy.SAME_ORIGIN.getPolicy());
|
||||
// @formatter:off
|
||||
this.http.headers()
|
||||
.crossOriginOpenerPolicy()
|
||||
.policy(CrossOriginOpenerPolicyServerHttpHeadersWriter.CrossOriginOpenerPolicy.SAME_ORIGIN_ALLOW_POPUPS)
|
||||
.and()
|
||||
.crossOriginEmbedderPolicy()
|
||||
.policy(CrossOriginEmbedderPolicyServerHttpHeadersWriter.CrossOriginEmbedderPolicy.REQUIRE_CORP)
|
||||
.and()
|
||||
.crossOriginResourcePolicy()
|
||||
.policy(CrossOriginResourcePolicyServerHttpHeadersWriter.CrossOriginResourcePolicy.SAME_ORIGIN);
|
||||
// @formatter:on
|
||||
assertHeaders();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headersWhenCrossOriginPoliciesCustomEnabledInLambdaThenCustomCrossOriginPoliciesWritten() {
|
||||
this.expectedHeaders.add(CrossOriginOpenerPolicyServerHttpHeadersWriter.OPENER_POLICY,
|
||||
CrossOriginOpenerPolicyServerHttpHeadersWriter.CrossOriginOpenerPolicy.SAME_ORIGIN_ALLOW_POPUPS
|
||||
.getPolicy());
|
||||
this.expectedHeaders.add(CrossOriginEmbedderPolicyServerHttpHeadersWriter.EMBEDDER_POLICY,
|
||||
CrossOriginEmbedderPolicyServerHttpHeadersWriter.CrossOriginEmbedderPolicy.REQUIRE_CORP.getPolicy());
|
||||
this.expectedHeaders.add(CrossOriginResourcePolicyServerHttpHeadersWriter.RESOURCE_POLICY,
|
||||
CrossOriginResourcePolicyServerHttpHeadersWriter.CrossOriginResourcePolicy.SAME_ORIGIN.getPolicy());
|
||||
// @formatter:off
|
||||
this.http.headers()
|
||||
.crossOriginOpenerPolicy((policy) -> policy
|
||||
.policy(CrossOriginOpenerPolicyServerHttpHeadersWriter.CrossOriginOpenerPolicy.SAME_ORIGIN_ALLOW_POPUPS)
|
||||
)
|
||||
.crossOriginEmbedderPolicy((policy) -> policy
|
||||
.policy(CrossOriginEmbedderPolicyServerHttpHeadersWriter.CrossOriginEmbedderPolicy.REQUIRE_CORP)
|
||||
)
|
||||
.crossOriginResourcePolicy((policy) -> policy
|
||||
.policy(CrossOriginResourcePolicyServerHttpHeadersWriter.CrossOriginResourcePolicy.SAME_ORIGIN)
|
||||
);
|
||||
// @formatter:on
|
||||
assertHeaders();
|
||||
}
|
||||
|
||||
private void expectHeaderNamesNotPresent(String... headerNames) {
|
||||
for (String headerName : headerNames) {
|
||||
this.expectedHeaders.remove(headerName);
|
||||
|
||||
Reference in New Issue
Block a user