Add support for Feature-Policy security header
This commit is contained in:
parent
9c478257d4
commit
c6ea447cc0
|
@ -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.
|
||||
|
@ -13,6 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.annotation.web.configurers;
|
||||
|
||||
import java.net.URI;
|
||||
|
@ -58,6 +59,7 @@ import org.springframework.util.Assert;
|
|||
* @author Tim Ysewyn
|
||||
* @author Joe Grandja
|
||||
* @author Eddú Meléndez
|
||||
* @author Vedran Pavic
|
||||
* @since 3.2
|
||||
*/
|
||||
public class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends
|
||||
|
@ -82,6 +84,8 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends
|
|||
|
||||
private final ReferrerPolicyConfig referrerPolicy = new ReferrerPolicyConfig();
|
||||
|
||||
private final FeaturePolicyConfig featurePolicy = new FeaturePolicyConfig();
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
|
@ -775,6 +779,7 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends
|
|||
addIfNotNull(writers, hpkp.writer);
|
||||
addIfNotNull(writers, contentSecurityPolicy.writer);
|
||||
addIfNotNull(writers, referrerPolicy.writer);
|
||||
addIfNotNull(writers, featurePolicy.writer);
|
||||
writers.addAll(headerWriters);
|
||||
return writers;
|
||||
}
|
||||
|
@ -848,4 +853,44 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>> extends
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows configuration for <a href="https://wicg.github.io/feature-policy/">Feature
|
||||
* Policy</a>.
|
||||
* <p>
|
||||
* Calling this method automatically enables (includes) the {@code Feature-Policy}
|
||||
* header in the response using the supplied policy directive(s).
|
||||
* <p>
|
||||
* Configuration is provided to the {@link FeaturePolicyHeaderWriter} which is
|
||||
* responsible for writing the header.
|
||||
*
|
||||
* @see FeaturePolicyHeaderWriter
|
||||
* @since 5.1
|
||||
* @return the {@link FeaturePolicyHeaderWriter} for additional configuration
|
||||
* @throws IllegalArgumentException if policyDirectives is {@code null} or empty
|
||||
*/
|
||||
public FeaturePolicyConfig featurePolicy(String policyDirectives) {
|
||||
this.featurePolicy.writer = new FeaturePolicyHeaderWriter(policyDirectives);
|
||||
return featurePolicy;
|
||||
}
|
||||
|
||||
public final class FeaturePolicyConfig {
|
||||
|
||||
private FeaturePolicyHeaderWriter writer;
|
||||
|
||||
private FeaturePolicyConfig() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows completing configuration of Feature Policy and continuing configuration
|
||||
* of headers.
|
||||
*
|
||||
* @return the {@link HeadersConfigurer} for additional configuration
|
||||
*/
|
||||
public HeadersConfigurer<H> and() {
|
||||
return HeadersConfigurer.this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -13,6 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.http;
|
||||
|
||||
import java.net.URI;
|
||||
|
@ -47,6 +48,7 @@ import org.w3c.dom.Node;
|
|||
* @author Marten Deinum
|
||||
* @author Tim Ysewyn
|
||||
* @author Eddú Meléndez
|
||||
* @author Vedran Pavic
|
||||
* @since 3.2
|
||||
*/
|
||||
public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
@ -85,6 +87,7 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
|||
|
||||
private static final String CONTENT_SECURITY_POLICY_ELEMENT = "content-security-policy";
|
||||
private static final String REFERRER_POLICY_ELEMENT = "referrer-policy";
|
||||
private static final String FEATURE_POLICY_ELEMENT = "feature-policy";
|
||||
|
||||
private static final String ALLOW_FROM = "ALLOW-FROM";
|
||||
|
||||
|
@ -114,6 +117,8 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
|||
|
||||
parseReferrerPolicyElement(element, parserContext);
|
||||
|
||||
parseFeaturePolicyElement(element, parserContext);
|
||||
|
||||
parseHeaderElements(element);
|
||||
|
||||
boolean noWriters = headerWriters.isEmpty();
|
||||
|
@ -313,6 +318,32 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
|||
headerWriters.add(headersWriter.getBeanDefinition());
|
||||
}
|
||||
|
||||
private void parseFeaturePolicyElement(Element element, ParserContext context) {
|
||||
Element featurePolicyElement = (element == null) ? null
|
||||
: DomUtils.getChildElementByTagName(element, FEATURE_POLICY_ELEMENT);
|
||||
if (featurePolicyElement != null) {
|
||||
addFeaturePolicy(featurePolicyElement, context);
|
||||
}
|
||||
}
|
||||
|
||||
private void addFeaturePolicy(Element featurePolicyElement, ParserContext context) {
|
||||
BeanDefinitionBuilder headersWriter = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(FeaturePolicyHeaderWriter.class);
|
||||
|
||||
String policyDirectives = featurePolicyElement
|
||||
.getAttribute(ATT_POLICY_DIRECTIVES);
|
||||
if (!StringUtils.hasText(policyDirectives)) {
|
||||
context.getReaderContext().error(
|
||||
ATT_POLICY_DIRECTIVES + " requires a 'value' to be set.",
|
||||
featurePolicyElement);
|
||||
}
|
||||
else {
|
||||
headersWriter.addConstructorArgValue(policyDirectives);
|
||||
}
|
||||
|
||||
headerWriters.add(headersWriter.getBeanDefinition());
|
||||
}
|
||||
|
||||
private void attrNotAllowed(ParserContext context, String attrName,
|
||||
String otherAttrName, Element element) {
|
||||
context.getReaderContext().error(
|
||||
|
|
|
@ -743,7 +743,7 @@ csrf-options.attlist &=
|
|||
|
||||
headers =
|
||||
## Element for configuration of the HeaderWritersFilter. Enables easy setting for the X-Frame-Options, X-XSS-Protection and X-Content-Type-Options headers.
|
||||
element headers { headers-options.attlist, (cache-control? & xss-protection? & hsts? & frame-options? & content-type-options? & hpkp? & content-security-policy? & referrer-policy? & header*)}
|
||||
element headers { headers-options.attlist, (cache-control? & xss-protection? & hsts? & frame-options? & content-type-options? & hpkp? & content-security-policy? & referrer-policy? & feature-policy? & header*)}
|
||||
headers-options.attlist &=
|
||||
## Specifies if the default headers should be disabled. Default false.
|
||||
attribute defaults-disabled {xsd:boolean}?
|
||||
|
@ -821,6 +821,13 @@ referrer-options.attlist &=
|
|||
## The policies for the Referrer-Policy header.
|
||||
attribute policy {"no-referrer","no-referrer-when-downgrade","same-origin","origin","strict-origin","origin-when-cross-origin","strict-origin-when-cross-origin","unsafe-url"}?
|
||||
|
||||
feature-policy =
|
||||
## Adds support for Feature Policy
|
||||
element feature-policy {feature-options.attlist}
|
||||
feature-options.attlist &=
|
||||
## The security policy directive(s) for the Feature-Policy header.
|
||||
attribute policy-directives {xsd:token}?
|
||||
|
||||
cache-control =
|
||||
## Adds Cache-Control no-cache, no-store, must-revalidate, Pragma no-cache, and Expires 0 for every request
|
||||
element cache-control {cache-control.attlist}
|
||||
|
|
|
@ -2253,6 +2253,7 @@
|
|||
<xs:element ref="security:hpkp"/>
|
||||
<xs:element ref="security:content-security-policy"/>
|
||||
<xs:element ref="security:referrer-policy"/>
|
||||
<xs:element ref="security:feature-policy"/>
|
||||
<xs:element ref="security:header"/>
|
||||
</xs:choice>
|
||||
<xs:attributeGroup ref="security:headers-options.attlist"/>
|
||||
|
@ -2464,6 +2465,21 @@
|
|||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
</xs:attributeGroup>
|
||||
<xs:element name="feature-policy">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Adds support for Feature Policy</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexType>
|
||||
<xs:attributeGroup ref="security:feature-options.attlist"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:attributeGroup name="feature-options.attlist">
|
||||
<xs:attribute name="policy-directives" type="xs:token">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The security policy directive(s) for the Feature-Policy header.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:attributeGroup>
|
||||
<xs:element name="cache-control">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Adds Cache-Control no-cache, no-store, must-revalidate, Pragma no-cache, and Expires 0 for
|
||||
|
@ -2719,4 +2735,4 @@
|
|||
<xs:enumeration value="LAST"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:schema>
|
||||
</xs:schema>
|
||||
|
|
|
@ -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.
|
||||
|
@ -13,6 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.config.annotation.web.configurers
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException
|
||||
|
@ -20,14 +21,17 @@ import org.springframework.security.config.annotation.BaseSpringSpec
|
|||
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 static org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter.ReferrerPolicy
|
||||
|
||||
/**
|
||||
* Tests for {@link HeadersConfigurer}.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Tim Ysewyn
|
||||
* @author Joe Grandja
|
||||
* @author Eddú Meléndez
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
class HeadersConfigurerTests extends BaseSpringSpec {
|
||||
|
||||
|
@ -497,4 +501,45 @@ class HeadersConfigurerTests extends BaseSpringSpec {
|
|||
}
|
||||
}
|
||||
|
||||
def "headers.featurePolicy default header"() {
|
||||
setup:
|
||||
loadConfig(FeaturePolicyDefaultConfig)
|
||||
request.secure = true
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request, response, chain)
|
||||
then:
|
||||
responseHeaders == ['Feature-Policy': 'geolocation \'self\'']
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class FeaturePolicyDefaultConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.headers()
|
||||
.defaultsDisabled()
|
||||
.featurePolicy("geolocation 'self'");
|
||||
}
|
||||
}
|
||||
|
||||
def "headers.featurePolicy empty policyDirectives"() {
|
||||
when:
|
||||
loadConfig(FeaturePolicyInvalidConfig)
|
||||
then:
|
||||
thrown(BeanCreationException)
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class FeaturePolicyInvalidConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.headers()
|
||||
.defaultsDisabled()
|
||||
.featurePolicy("");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -241,6 +241,7 @@ This allows HTTPS websites to resist impersonation by attackers using mis-issued
|
|||
** `Content-Security-Policy` or `Content-Security-Policy-Report-Only` - Can be set using the <<nsa-content-security-policy,content-security-policy>> element.
|
||||
https://www.w3.org/TR/CSP2/[Content Security Policy (CSP)] is a mechanism that web applications can leverage to mitigate content injection vulnerabilities, such as cross-site scripting (XSS).
|
||||
** `Referrer-Policy` - Can be set using the <<nsa-referrer-policy,referrer-policy>> element, https://www.w3.org/TR/referrer-policy/[Referrer-Policy] is a mechanism that web applications can leverage to manage the referrer field, which contains the last page the user was on.
|
||||
** `Feature-Policy` - Can be set using the <<nsa-feature-policy,feature-policy>> element, https://wicg.github.io/feature-policy/[Feature-Policy] is a mechanism that allows web developers to selectively enable, disable, and modify the behavior of certain APIs and web features in the browser.
|
||||
|
||||
[[nsa-headers-attributes]]
|
||||
===== <headers> Attributes
|
||||
|
@ -272,6 +273,7 @@ The default is false (the headers are enabled).
|
|||
* <<nsa-cache-control,cache-control>>
|
||||
* <<nsa-content-security-policy,content-security-policy>>
|
||||
* <<nsa-content-type-options,content-type-options>>
|
||||
* <<nsa-feature-policy,feature-policy>>
|
||||
* <<nsa-frame-options,frame-options>>
|
||||
* <<nsa-header,header>>
|
||||
* <<nsa-hpkp,hpkp>>
|
||||
|
@ -459,6 +461,24 @@ Default "no-referrer".
|
|||
|
||||
|
||||
|
||||
[[nsa-feature-policy]]
|
||||
==== <feature-policy>
|
||||
When enabled adds the https://wicg.github.io/feature-policy/[Feature Policy] header to the response.
|
||||
|
||||
[[nsa-feature-policy-attributes]]
|
||||
===== <feature-policy> Attributes
|
||||
|
||||
[[nsa-feature-policy-policy-directives]]
|
||||
* **policy-directives**
|
||||
The security policy directive(s) for the Feature-Policy header.
|
||||
|
||||
[[nsa-feature-policy-parents]]
|
||||
===== Parent Elements of <feature-policy>
|
||||
|
||||
* <<nsa-headers,headers>>
|
||||
|
||||
|
||||
|
||||
[[nsa-frame-options]]
|
||||
==== <frame-options>
|
||||
When enabled adds the http://tools.ietf.org/html/draft-ietf-websec-x-frame-options[X-Frame-Options header] to the response, this allows newer browsers to do some security checks and prevent http://en.wikipedia.org/wiki/Clickjacking[clickjacking] attacks.
|
||||
|
|
|
@ -714,6 +714,56 @@ protected void configure(HttpSecurity http) throws Exception {
|
|||
----
|
||||
|
||||
|
||||
[[headers-feature]]
|
||||
==== Feature Policy
|
||||
|
||||
https://wicg.github.io/feature-policy/[Feature Policy] is a mechanism that allows web developers to selectively enable, disable, and modify the behavior of certain APIs and web features in the browser.
|
||||
|
||||
[source]
|
||||
----
|
||||
Feature-Policy: geolocation 'self'
|
||||
----
|
||||
|
||||
With Feature Policy, developers can opt-in to a set of "policies" for the browser to enforce on specific features used throughout your site.
|
||||
These policies restrict what APIs the site can access or modify the browser's default behavior for certain features.
|
||||
|
||||
[[headers-feature-configure]]
|
||||
===== Configuring Feature Policy
|
||||
|
||||
Spring Security *_doesn't add_* Feature Policy header by default.
|
||||
|
||||
You can enable the Feature-Policy header using XML configuration with the <<nsa-feature-policy,<feature-policy>>> element as shown below:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
<!-- ... -->
|
||||
|
||||
<headers>
|
||||
<feature-policy policy-directives="geolocation 'self'" />
|
||||
</headers>
|
||||
</http>
|
||||
----
|
||||
|
||||
Similarly, you can enable the Feature Policy header using Java configuration as shown below:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@EnableWebSecurity
|
||||
public class WebSecurityConfig extends
|
||||
WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
// ...
|
||||
.headers()
|
||||
.featurePolicy("geolocation 'self'");
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
[[headers-custom]]
|
||||
=== Custom Headers
|
||||
Spring Security has mechanisms to make it convenient to add the more common security headers to your application.
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.web.header.writers;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.security.web.header.HeaderWriter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Provides support for <a href="https://wicg.github.io/feature-policy/">Feature
|
||||
* Policy</a>.
|
||||
* <p>
|
||||
* Feature Policy allows web developers to selectively enable, disable, and modify the
|
||||
* behavior of certain APIs and web features in the browser.
|
||||
* <p>
|
||||
* A declaration of a feature policy contains a set of security policy directives, each
|
||||
* responsible for declaring the restrictions for a particular feature type.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
* @since 5.1
|
||||
*/
|
||||
public final class FeaturePolicyHeaderWriter implements HeaderWriter {
|
||||
|
||||
private static final String FEATURE_POLICY_HEADER = "Feature-Policy";
|
||||
|
||||
private String policyDirectives;
|
||||
|
||||
/**
|
||||
* Create a new instance of {@link FeaturePolicyHeaderWriter} with supplied security
|
||||
* policy directive(s).
|
||||
*
|
||||
* @param policyDirectives the security policy directive(s)
|
||||
* @throws IllegalArgumentException if policyDirectives is {@code null} or empty
|
||||
*/
|
||||
public FeaturePolicyHeaderWriter(String policyDirectives) {
|
||||
setPolicyDirectives(policyDirectives);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeHeaders(HttpServletRequest request, HttpServletResponse response) {
|
||||
response.setHeader(FEATURE_POLICY_HEADER, this.policyDirectives);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the security policy directive(s) to be used in the response header.
|
||||
*
|
||||
* @param policyDirectives the security policy directive(s)
|
||||
* @throws IllegalArgumentException if policyDirectives is {@code null} or empty
|
||||
*/
|
||||
public void setPolicyDirectives(String policyDirectives) {
|
||||
Assert.hasLength(policyDirectives, "policyDirectives must not be null or empty");
|
||||
this.policyDirectives = policyDirectives;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getName() + " [policyDirectives=" + this.policyDirectives + "]";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.web.header.writers;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
/**
|
||||
* Tests for {@link FeaturePolicyHeaderWriter}.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
public class FeaturePolicyHeaderWriterTests {
|
||||
|
||||
private static final String DEFAULT_POLICY_DIRECTIVES = "geolocation 'self'";
|
||||
|
||||
private MockHttpServletRequest request;
|
||||
|
||||
private MockHttpServletResponse response;
|
||||
|
||||
private FeaturePolicyHeaderWriter writer;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.request = new MockHttpServletRequest();
|
||||
this.response = new MockHttpServletResponse();
|
||||
this.writer = new FeaturePolicyHeaderWriter(DEFAULT_POLICY_DIRECTIVES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void writeHeadersFeaturePolicyDefault() {
|
||||
writer.writeHeaders(this.request, this.response);
|
||||
|
||||
assertThat(this.response.getHeaderNames()).hasSize(1);
|
||||
assertThat(this.response.getHeader("Feature-Policy"))
|
||||
.isEqualTo(DEFAULT_POLICY_DIRECTIVES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWriterWithNullDirectivesShouldThrowException() {
|
||||
assertThatThrownBy(() -> new FeaturePolicyHeaderWriter(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("policyDirectives must not be null or empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWriterWithEmptyDirectivesShouldThrowException() {
|
||||
assertThatThrownBy(() -> new FeaturePolicyHeaderWriter(""))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("policyDirectives must not be null or empty");
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue