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:
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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -31,6 +31,9 @@ import org.springframework.security.web.header.HeaderWriter;
|
||||||
import org.springframework.security.web.header.HeaderWriterFilter;
|
import org.springframework.security.web.header.HeaderWriterFilter;
|
||||||
import org.springframework.security.web.header.writers.CacheControlHeadersWriter;
|
import org.springframework.security.web.header.writers.CacheControlHeadersWriter;
|
||||||
import org.springframework.security.web.header.writers.ContentSecurityPolicyHeaderWriter;
|
import org.springframework.security.web.header.writers.ContentSecurityPolicyHeaderWriter;
|
||||||
|
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.FeaturePolicyHeaderWriter;
|
import org.springframework.security.web.header.writers.FeaturePolicyHeaderWriter;
|
||||||
import org.springframework.security.web.header.writers.HpkpHeaderWriter;
|
import org.springframework.security.web.header.writers.HpkpHeaderWriter;
|
||||||
import org.springframework.security.web.header.writers.HstsHeaderWriter;
|
import org.springframework.security.web.header.writers.HstsHeaderWriter;
|
||||||
|
@ -97,6 +100,12 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
||||||
|
|
||||||
private final PermissionsPolicyConfig permissionsPolicy = new PermissionsPolicyConfig();
|
private final PermissionsPolicyConfig permissionsPolicy = new PermissionsPolicyConfig();
|
||||||
|
|
||||||
|
private final CrossOriginOpenerPolicyConfig crossOriginOpenerPolicy = new CrossOriginOpenerPolicyConfig();
|
||||||
|
|
||||||
|
private final CrossOriginEmbedderPolicyConfig crossOriginEmbedderPolicy = new CrossOriginEmbedderPolicyConfig();
|
||||||
|
|
||||||
|
private final CrossOriginResourcePolicyConfig crossOriginResourcePolicy = new CrossOriginResourcePolicyConfig();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
*
|
*
|
||||||
|
@ -392,6 +401,9 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
||||||
addIfNotNull(writers, this.referrerPolicy.writer);
|
addIfNotNull(writers, this.referrerPolicy.writer);
|
||||||
addIfNotNull(writers, this.featurePolicy.writer);
|
addIfNotNull(writers, this.featurePolicy.writer);
|
||||||
addIfNotNull(writers, this.permissionsPolicy.writer);
|
addIfNotNull(writers, this.permissionsPolicy.writer);
|
||||||
|
addIfNotNull(writers, this.crossOriginOpenerPolicy.writer);
|
||||||
|
addIfNotNull(writers, this.crossOriginEmbedderPolicy.writer);
|
||||||
|
addIfNotNull(writers, this.crossOriginResourcePolicy.writer);
|
||||||
writers.addAll(this.headerWriters);
|
writers.addAll(this.headerWriters);
|
||||||
return writers;
|
return writers;
|
||||||
}
|
}
|
||||||
|
@ -544,6 +556,129 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
||||||
return this.permissionsPolicy;
|
return this.permissionsPolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows configuration for <a href=
|
||||||
|
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy">
|
||||||
|
* Cross-Origin-Opener-Policy</a> header.
|
||||||
|
* <p>
|
||||||
|
* Configuration is provided to the {@link CrossOriginOpenerPolicyHeaderWriter} which
|
||||||
|
* responsible for writing the header.
|
||||||
|
* </p>
|
||||||
|
* @return the {@link CrossOriginOpenerPolicyConfig} for additional confniguration
|
||||||
|
* @since 5.7
|
||||||
|
* @see CrossOriginOpenerPolicyHeaderWriter
|
||||||
|
*/
|
||||||
|
public CrossOriginOpenerPolicyConfig crossOriginOpenerPolicy() {
|
||||||
|
this.crossOriginOpenerPolicy.writer = new CrossOriginOpenerPolicyHeaderWriter();
|
||||||
|
return this.crossOriginOpenerPolicy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows configuration for <a href=
|
||||||
|
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy">
|
||||||
|
* Cross-Origin-Opener-Policy</a> header.
|
||||||
|
* <p>
|
||||||
|
* Calling this method automatically enables (includes) the
|
||||||
|
* {@code Cross-Origin-Opener-Policy} header in the response using the supplied
|
||||||
|
* policy.
|
||||||
|
* <p>
|
||||||
|
* <p>
|
||||||
|
* Configuration is provided to the {@link CrossOriginOpenerPolicyHeaderWriter} which
|
||||||
|
* responsible for writing the header.
|
||||||
|
* </p>
|
||||||
|
* @return the {@link HeadersConfigurer} for additional customizations
|
||||||
|
* @since 5.7
|
||||||
|
* @see CrossOriginOpenerPolicyHeaderWriter
|
||||||
|
*/
|
||||||
|
public HeadersConfigurer<H> crossOriginOpenerPolicy(
|
||||||
|
Customizer<CrossOriginOpenerPolicyConfig> crossOriginOpenerPolicyCustomizer) {
|
||||||
|
this.crossOriginOpenerPolicy.writer = new CrossOriginOpenerPolicyHeaderWriter();
|
||||||
|
crossOriginOpenerPolicyCustomizer.customize(this.crossOriginOpenerPolicy);
|
||||||
|
return HeadersConfigurer.this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows configuration for <a href=
|
||||||
|
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy">
|
||||||
|
* Cross-Origin-Embedder-Policy</a> header.
|
||||||
|
* <p>
|
||||||
|
* Configuration is provided to the {@link CrossOriginEmbedderPolicyHeaderWriter}
|
||||||
|
* which is responsible for writing the header.
|
||||||
|
* </p>
|
||||||
|
* @return the {@link CrossOriginEmbedderPolicyConfig} for additional customizations
|
||||||
|
* @since 5.7
|
||||||
|
* @see CrossOriginEmbedderPolicyHeaderWriter
|
||||||
|
*/
|
||||||
|
public CrossOriginEmbedderPolicyConfig crossOriginEmbedderPolicy() {
|
||||||
|
this.crossOriginEmbedderPolicy.writer = new CrossOriginEmbedderPolicyHeaderWriter();
|
||||||
|
return this.crossOriginEmbedderPolicy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows configuration for <a href=
|
||||||
|
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy">
|
||||||
|
* Cross-Origin-Embedder-Policy</a> header.
|
||||||
|
* <p>
|
||||||
|
* Calling this method automatically enables (includes) the
|
||||||
|
* {@code Cross-Origin-Embedder-Policy} header in the response using the supplied
|
||||||
|
* policy.
|
||||||
|
* <p>
|
||||||
|
* <p>
|
||||||
|
* Configuration is provided to the {@link CrossOriginEmbedderPolicyHeaderWriter}
|
||||||
|
* which is responsible for writing the header.
|
||||||
|
* </p>
|
||||||
|
* @return the {@link HeadersConfigurer} for additional customizations
|
||||||
|
* @since 5.7
|
||||||
|
* @see CrossOriginEmbedderPolicyHeaderWriter
|
||||||
|
*/
|
||||||
|
public HeadersConfigurer<H> crossOriginEmbedderPolicy(
|
||||||
|
Customizer<CrossOriginEmbedderPolicyConfig> crossOriginEmbedderPolicyCustomizer) {
|
||||||
|
this.crossOriginEmbedderPolicy.writer = new CrossOriginEmbedderPolicyHeaderWriter();
|
||||||
|
crossOriginEmbedderPolicyCustomizer.customize(this.crossOriginEmbedderPolicy);
|
||||||
|
return HeadersConfigurer.this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows configuration for <a href=
|
||||||
|
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy">
|
||||||
|
* Cross-Origin-Resource-Policy</a> header.
|
||||||
|
* <p>
|
||||||
|
* Configuration is provided to the {@link CrossOriginResourcePolicyHeaderWriter}
|
||||||
|
* which is responsible for writing the header:
|
||||||
|
* </p>
|
||||||
|
* @return the {@link HeadersConfigurer} for additional customizations
|
||||||
|
* @since 5.7
|
||||||
|
* @see CrossOriginResourcePolicyHeaderWriter
|
||||||
|
*/
|
||||||
|
public CrossOriginResourcePolicyConfig crossOriginResourcePolicy() {
|
||||||
|
this.crossOriginResourcePolicy.writer = new CrossOriginResourcePolicyHeaderWriter();
|
||||||
|
return this.crossOriginResourcePolicy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows configuration for <a href=
|
||||||
|
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy">
|
||||||
|
* Cross-Origin-Resource-Policy</a> header.
|
||||||
|
* <p>
|
||||||
|
* Calling this method automatically enables (includes) the
|
||||||
|
* {@code Cross-Origin-Resource-Policy} header in the response using the supplied
|
||||||
|
* policy.
|
||||||
|
* <p>
|
||||||
|
* <p>
|
||||||
|
* Configuration is provided to the {@link CrossOriginResourcePolicyHeaderWriter}
|
||||||
|
* which is responsible for writing the header:
|
||||||
|
* </p>
|
||||||
|
* @return the {@link HeadersConfigurer} for additional customizations
|
||||||
|
* @since 5.7
|
||||||
|
* @see CrossOriginResourcePolicyHeaderWriter
|
||||||
|
*/
|
||||||
|
public HeadersConfigurer<H> crossOriginResourcePolicy(
|
||||||
|
Customizer<CrossOriginResourcePolicyConfig> crossOriginResourcePolicyCustomizer) {
|
||||||
|
this.crossOriginResourcePolicy.writer = new CrossOriginResourcePolicyHeaderWriter();
|
||||||
|
crossOriginResourcePolicyCustomizer.customize(this.crossOriginResourcePolicy);
|
||||||
|
return HeadersConfigurer.this;
|
||||||
|
}
|
||||||
|
|
||||||
public final class ContentTypeOptionsConfig {
|
public final class ContentTypeOptionsConfig {
|
||||||
|
|
||||||
private XContentTypeOptionsHeaderWriter writer;
|
private XContentTypeOptionsHeaderWriter writer;
|
||||||
|
@ -1142,4 +1277,96 @@ public class HeadersConfigurer<H extends HttpSecurityBuilder<H>>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class CrossOriginOpenerPolicyConfig {
|
||||||
|
|
||||||
|
private CrossOriginOpenerPolicyHeaderWriter writer;
|
||||||
|
|
||||||
|
public CrossOriginOpenerPolicyConfig() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the policy to be used in the {@code Cross-Origin-Opener-Policy} header
|
||||||
|
* @param openerPolicy a {@code Cross-Origin-Opener-Policy}
|
||||||
|
* @return the {@link CrossOriginOpenerPolicyConfig} for additional configuration
|
||||||
|
* @throws IllegalArgumentException if openerPolicy is null
|
||||||
|
*/
|
||||||
|
public CrossOriginOpenerPolicyConfig policy(
|
||||||
|
CrossOriginOpenerPolicyHeaderWriter.CrossOriginOpenerPolicy openerPolicy) {
|
||||||
|
this.writer.setPolicy(openerPolicy);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows completing configuration of Cross Origin Opener Policy and continuing
|
||||||
|
* configuration of headers.
|
||||||
|
* @return the {@link HeadersConfigurer} for additional configuration
|
||||||
|
*/
|
||||||
|
public HeadersConfigurer<H> and() {
|
||||||
|
return HeadersConfigurer.this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class CrossOriginEmbedderPolicyConfig {
|
||||||
|
|
||||||
|
private CrossOriginEmbedderPolicyHeaderWriter writer;
|
||||||
|
|
||||||
|
public CrossOriginEmbedderPolicyConfig() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the policy to be used in the {@code Cross-Origin-Embedder-Policy} header
|
||||||
|
* @param embedderPolicy a {@code Cross-Origin-Embedder-Policy}
|
||||||
|
* @return the {@link CrossOriginEmbedderPolicyConfig} for additional
|
||||||
|
* configuration
|
||||||
|
* @throws IllegalArgumentException if embedderPolicy is null
|
||||||
|
*/
|
||||||
|
public CrossOriginEmbedderPolicyConfig policy(
|
||||||
|
CrossOriginEmbedderPolicyHeaderWriter.CrossOriginEmbedderPolicy embedderPolicy) {
|
||||||
|
this.writer.setPolicy(embedderPolicy);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows completing configuration of Cross-Origin-Embedder-Policy and continuing
|
||||||
|
* configuration of headers.
|
||||||
|
* @return the {@link HeadersConfigurer} for additional configuration
|
||||||
|
*/
|
||||||
|
public HeadersConfigurer<H> and() {
|
||||||
|
return HeadersConfigurer.this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class CrossOriginResourcePolicyConfig {
|
||||||
|
|
||||||
|
private CrossOriginResourcePolicyHeaderWriter writer;
|
||||||
|
|
||||||
|
public CrossOriginResourcePolicyConfig() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the policy to be used in the {@code Cross-Origin-Resource-Policy} header
|
||||||
|
* @param resourcePolicy a {@code Cross-Origin-Resource-Policy}
|
||||||
|
* @return the {@link CrossOriginResourcePolicyConfig} for additional
|
||||||
|
* configuration
|
||||||
|
* @throws IllegalArgumentException if resourcePolicy is null
|
||||||
|
*/
|
||||||
|
public CrossOriginResourcePolicyConfig policy(
|
||||||
|
CrossOriginResourcePolicyHeaderWriter.CrossOriginResourcePolicy resourcePolicy) {
|
||||||
|
this.writer.setPolicy(resourcePolicy);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows completing configuration of Cross-Origin-Resource-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-2019 the original author or authors.
|
* Copyright 2002-2021 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -36,6 +36,9 @@ import org.springframework.beans.factory.xml.ParserContext;
|
||||||
import org.springframework.security.web.header.HeaderWriterFilter;
|
import org.springframework.security.web.header.HeaderWriterFilter;
|
||||||
import org.springframework.security.web.header.writers.CacheControlHeadersWriter;
|
import org.springframework.security.web.header.writers.CacheControlHeadersWriter;
|
||||||
import org.springframework.security.web.header.writers.ContentSecurityPolicyHeaderWriter;
|
import org.springframework.security.web.header.writers.ContentSecurityPolicyHeaderWriter;
|
||||||
|
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.FeaturePolicyHeaderWriter;
|
import org.springframework.security.web.header.writers.FeaturePolicyHeaderWriter;
|
||||||
import org.springframework.security.web.header.writers.HpkpHeaderWriter;
|
import org.springframework.security.web.header.writers.HpkpHeaderWriter;
|
||||||
import org.springframework.security.web.header.writers.HstsHeaderWriter;
|
import org.springframework.security.web.header.writers.HstsHeaderWriter;
|
||||||
|
@ -122,6 +125,12 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
||||||
|
|
||||||
private static final String PERMISSIONS_POLICY_ELEMENT = "permissions-policy";
|
private static final String PERMISSIONS_POLICY_ELEMENT = "permissions-policy";
|
||||||
|
|
||||||
|
private static final String CROSS_ORIGIN_OPENER_POLICY_ELEMENT = "cross-origin-opener-policy";
|
||||||
|
|
||||||
|
private static final String CROSS_ORIGIN_EMBEDDER_POLICY_ELEMENT = "cross-origin-embedder-policy";
|
||||||
|
|
||||||
|
private static final String CROSS_ORIGIN_RESOURCE_POLICY_ELEMENT = "cross-origin-resource-policy";
|
||||||
|
|
||||||
private static final String ALLOW_FROM = "ALLOW-FROM";
|
private static final String ALLOW_FROM = "ALLOW-FROM";
|
||||||
|
|
||||||
private ManagedList<BeanMetadataElement> headerWriters;
|
private ManagedList<BeanMetadataElement> headerWriters;
|
||||||
|
@ -144,6 +153,9 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
||||||
parseReferrerPolicyElement(element, parserContext);
|
parseReferrerPolicyElement(element, parserContext);
|
||||||
parseFeaturePolicyElement(element, parserContext);
|
parseFeaturePolicyElement(element, parserContext);
|
||||||
parsePermissionsPolicyElement(element, parserContext);
|
parsePermissionsPolicyElement(element, parserContext);
|
||||||
|
parseCrossOriginOpenerPolicy(disabled, element);
|
||||||
|
parseCrossOriginEmbedderPolicy(disabled, element);
|
||||||
|
parseCrossOriginResourcePolicy(disabled, element);
|
||||||
parseHeaderElements(element);
|
parseHeaderElements(element);
|
||||||
boolean noWriters = this.headerWriters.isEmpty();
|
boolean noWriters = this.headerWriters.isEmpty();
|
||||||
if (disabled && !noWriters) {
|
if (disabled && !noWriters) {
|
||||||
|
@ -376,6 +388,75 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
|
||||||
this.headerWriters.add(headersWriter.getBeanDefinition());
|
this.headerWriters.add(headersWriter.getBeanDefinition());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void parseCrossOriginOpenerPolicy(boolean elementDisabled, Element element) {
|
||||||
|
if (elementDisabled || element == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CrossOriginOpenerPolicyHeaderWriter writer = new CrossOriginOpenerPolicyHeaderWriter();
|
||||||
|
Element crossOriginOpenerPolicyElement = DomUtils.getChildElementByTagName(element,
|
||||||
|
CROSS_ORIGIN_OPENER_POLICY_ELEMENT);
|
||||||
|
if (crossOriginOpenerPolicyElement != null) {
|
||||||
|
addCrossOriginOpenerPolicy(crossOriginOpenerPolicyElement, writer);
|
||||||
|
}
|
||||||
|
BeanDefinitionBuilder builder = BeanDefinitionBuilder
|
||||||
|
.genericBeanDefinition(CrossOriginOpenerPolicyHeaderWriter.class, () -> writer);
|
||||||
|
this.headerWriters.add(builder.getBeanDefinition());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseCrossOriginEmbedderPolicy(boolean elementDisabled, Element element) {
|
||||||
|
if (elementDisabled || element == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CrossOriginEmbedderPolicyHeaderWriter writer = new CrossOriginEmbedderPolicyHeaderWriter();
|
||||||
|
Element crossOriginEmbedderPolicyElement = DomUtils.getChildElementByTagName(element,
|
||||||
|
CROSS_ORIGIN_EMBEDDER_POLICY_ELEMENT);
|
||||||
|
if (crossOriginEmbedderPolicyElement != null) {
|
||||||
|
addCrossOriginEmbedderPolicy(crossOriginEmbedderPolicyElement, writer);
|
||||||
|
}
|
||||||
|
BeanDefinitionBuilder builder = BeanDefinitionBuilder
|
||||||
|
.genericBeanDefinition(CrossOriginEmbedderPolicyHeaderWriter.class, () -> writer);
|
||||||
|
this.headerWriters.add(builder.getBeanDefinition());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseCrossOriginResourcePolicy(boolean elementDisabled, Element element) {
|
||||||
|
if (elementDisabled || element == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CrossOriginResourcePolicyHeaderWriter writer = new CrossOriginResourcePolicyHeaderWriter();
|
||||||
|
Element crossOriginResourcePolicyElement = DomUtils.getChildElementByTagName(element,
|
||||||
|
CROSS_ORIGIN_RESOURCE_POLICY_ELEMENT);
|
||||||
|
if (crossOriginResourcePolicyElement != null) {
|
||||||
|
addCrossOriginResourcePolicy(crossOriginResourcePolicyElement, writer);
|
||||||
|
}
|
||||||
|
BeanDefinitionBuilder builder = BeanDefinitionBuilder
|
||||||
|
.genericBeanDefinition(CrossOriginResourcePolicyHeaderWriter.class, () -> writer);
|
||||||
|
this.headerWriters.add(builder.getBeanDefinition());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addCrossOriginResourcePolicy(Element crossOriginResourcePolicyElement,
|
||||||
|
CrossOriginResourcePolicyHeaderWriter writer) {
|
||||||
|
String policy = crossOriginResourcePolicyElement.getAttribute(ATT_POLICY);
|
||||||
|
if (StringUtils.hasText(policy)) {
|
||||||
|
writer.setPolicy(CrossOriginResourcePolicyHeaderWriter.CrossOriginResourcePolicy.from(policy));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addCrossOriginEmbedderPolicy(Element crossOriginEmbedderPolicyElement,
|
||||||
|
CrossOriginEmbedderPolicyHeaderWriter writer) {
|
||||||
|
String policy = crossOriginEmbedderPolicyElement.getAttribute(ATT_POLICY);
|
||||||
|
if (StringUtils.hasText(policy)) {
|
||||||
|
writer.setPolicy(CrossOriginEmbedderPolicyHeaderWriter.CrossOriginEmbedderPolicy.from(policy));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addCrossOriginOpenerPolicy(Element crossOriginOpenerPolicyElement,
|
||||||
|
CrossOriginOpenerPolicyHeaderWriter writer) {
|
||||||
|
String policy = crossOriginOpenerPolicyElement.getAttribute(ATT_POLICY);
|
||||||
|
if (StringUtils.hasText(policy)) {
|
||||||
|
writer.setPolicy(CrossOriginOpenerPolicyHeaderWriter.CrossOriginOpenerPolicy.from(policy));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void attrNotAllowed(ParserContext context, String attrName, String otherAttrName, Element element) {
|
private void attrNotAllowed(ParserContext context, String attrName, String otherAttrName, Element element) {
|
||||||
context.getReaderContext().error("Only one of '" + attrName + "' or '" + otherAttrName + "' can be set.",
|
context.getReaderContext().error("Only one of '" + attrName + "' or '" + otherAttrName + "' can be set.",
|
||||||
element);
|
element);
|
||||||
|
|
|
@ -149,6 +149,12 @@ import org.springframework.security.web.server.header.CacheControlServerHttpHead
|
||||||
import org.springframework.security.web.server.header.CompositeServerHttpHeadersWriter;
|
import org.springframework.security.web.server.header.CompositeServerHttpHeadersWriter;
|
||||||
import org.springframework.security.web.server.header.ContentSecurityPolicyServerHttpHeadersWriter;
|
import org.springframework.security.web.server.header.ContentSecurityPolicyServerHttpHeadersWriter;
|
||||||
import org.springframework.security.web.server.header.ContentTypeOptionsServerHttpHeadersWriter;
|
import org.springframework.security.web.server.header.ContentTypeOptionsServerHttpHeadersWriter;
|
||||||
|
import org.springframework.security.web.server.header.CrossOriginEmbedderPolicyServerHttpHeadersWriter;
|
||||||
|
import org.springframework.security.web.server.header.CrossOriginEmbedderPolicyServerHttpHeadersWriter.CrossOriginEmbedderPolicy;
|
||||||
|
import org.springframework.security.web.server.header.CrossOriginOpenerPolicyServerHttpHeadersWriter;
|
||||||
|
import org.springframework.security.web.server.header.CrossOriginOpenerPolicyServerHttpHeadersWriter.CrossOriginOpenerPolicy;
|
||||||
|
import org.springframework.security.web.server.header.CrossOriginResourcePolicyServerHttpHeadersWriter;
|
||||||
|
import org.springframework.security.web.server.header.CrossOriginResourcePolicyServerHttpHeadersWriter.CrossOriginResourcePolicy;
|
||||||
import org.springframework.security.web.server.header.FeaturePolicyServerHttpHeadersWriter;
|
import org.springframework.security.web.server.header.FeaturePolicyServerHttpHeadersWriter;
|
||||||
import org.springframework.security.web.server.header.HttpHeaderWriterWebFilter;
|
import org.springframework.security.web.server.header.HttpHeaderWriterWebFilter;
|
||||||
import org.springframework.security.web.server.header.PermissionsPolicyServerHttpHeadersWriter;
|
import org.springframework.security.web.server.header.PermissionsPolicyServerHttpHeadersWriter;
|
||||||
|
@ -2380,10 +2386,17 @@ public class ServerHttpSecurity {
|
||||||
|
|
||||||
private ReferrerPolicyServerHttpHeadersWriter referrerPolicy = new ReferrerPolicyServerHttpHeadersWriter();
|
private ReferrerPolicyServerHttpHeadersWriter referrerPolicy = new ReferrerPolicyServerHttpHeadersWriter();
|
||||||
|
|
||||||
|
private CrossOriginOpenerPolicyServerHttpHeadersWriter crossOriginOpenerPolicy = new CrossOriginOpenerPolicyServerHttpHeadersWriter();
|
||||||
|
|
||||||
|
private CrossOriginEmbedderPolicyServerHttpHeadersWriter crossOriginEmbedderPolicy = new CrossOriginEmbedderPolicyServerHttpHeadersWriter();
|
||||||
|
|
||||||
|
private CrossOriginResourcePolicyServerHttpHeadersWriter crossOriginResourcePolicy = new CrossOriginResourcePolicyServerHttpHeadersWriter();
|
||||||
|
|
||||||
private HeaderSpec() {
|
private HeaderSpec() {
|
||||||
this.writers = new ArrayList<>(Arrays.asList(this.cacheControl, this.contentTypeOptions, this.hsts,
|
this.writers = new ArrayList<>(Arrays.asList(this.cacheControl, this.contentTypeOptions, this.hsts,
|
||||||
this.frameOptions, this.xss, this.featurePolicy, this.permissionsPolicy, this.contentSecurityPolicy,
|
this.frameOptions, this.xss, this.featurePolicy, this.permissionsPolicy, this.contentSecurityPolicy,
|
||||||
this.referrerPolicy));
|
this.referrerPolicy, this.crossOriginOpenerPolicy, this.crossOriginEmbedderPolicy,
|
||||||
|
this.crossOriginResourcePolicy));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2595,6 +2608,84 @@ public class ServerHttpSecurity {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the <a href=
|
||||||
|
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy">
|
||||||
|
* Cross-Origin-Opener-Policy</a> header.
|
||||||
|
* @return the {@link CrossOriginOpenerPolicySpec} to configure
|
||||||
|
* @since 5.7
|
||||||
|
* @see CrossOriginOpenerPolicyServerHttpHeadersWriter
|
||||||
|
*/
|
||||||
|
public CrossOriginOpenerPolicySpec crossOriginOpenerPolicy() {
|
||||||
|
return new CrossOriginOpenerPolicySpec();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the <a href=
|
||||||
|
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy">
|
||||||
|
* Cross-Origin-Opener-Policy</a> header.
|
||||||
|
* @return the {@link HeaderSpec} to customize
|
||||||
|
* @since 5.7
|
||||||
|
* @see CrossOriginOpenerPolicyServerHttpHeadersWriter
|
||||||
|
*/
|
||||||
|
public HeaderSpec crossOriginOpenerPolicy(
|
||||||
|
Customizer<CrossOriginOpenerPolicySpec> crossOriginOpenerPolicyCustomizer) {
|
||||||
|
crossOriginOpenerPolicyCustomizer.customize(new CrossOriginOpenerPolicySpec());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the <a href=
|
||||||
|
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy">
|
||||||
|
* Cross-Origin-Embedder-Policy</a> header.
|
||||||
|
* @return the {@link CrossOriginEmbedderPolicySpec} to configure
|
||||||
|
* @since 5.7
|
||||||
|
* @see CrossOriginEmbedderPolicyServerHttpHeadersWriter
|
||||||
|
*/
|
||||||
|
public CrossOriginEmbedderPolicySpec crossOriginEmbedderPolicy() {
|
||||||
|
return new CrossOriginEmbedderPolicySpec();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the <a href=
|
||||||
|
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy">
|
||||||
|
* Cross-Origin-Embedder-Policy</a> header.
|
||||||
|
* @return the {@link HeaderSpec} to customize
|
||||||
|
* @since 5.7
|
||||||
|
* @see CrossOriginEmbedderPolicyServerHttpHeadersWriter
|
||||||
|
*/
|
||||||
|
public HeaderSpec crossOriginEmbedderPolicy(
|
||||||
|
Customizer<CrossOriginEmbedderPolicySpec> crossOriginEmbedderPolicyCustomizer) {
|
||||||
|
crossOriginEmbedderPolicyCustomizer.customize(new CrossOriginEmbedderPolicySpec());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the <a href=
|
||||||
|
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy">
|
||||||
|
* Cross-Origin-Resource-Policy</a> header.
|
||||||
|
* @return the {@link CrossOriginResourcePolicySpec} to configure
|
||||||
|
* @since 5.7
|
||||||
|
* @see CrossOriginResourcePolicyServerHttpHeadersWriter
|
||||||
|
*/
|
||||||
|
public CrossOriginResourcePolicySpec crossOriginResourcePolicy() {
|
||||||
|
return new CrossOriginResourcePolicySpec();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the <a href=
|
||||||
|
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy">
|
||||||
|
* Cross-Origin-Resource-Policy</a> header.
|
||||||
|
* @return the {@link HeaderSpec} to customize
|
||||||
|
* @since 5.7
|
||||||
|
* @see CrossOriginResourcePolicyServerHttpHeadersWriter
|
||||||
|
*/
|
||||||
|
public HeaderSpec crossOriginResourcePolicy(
|
||||||
|
Customizer<CrossOriginResourcePolicySpec> crossOriginResourcePolicyCustomizer) {
|
||||||
|
crossOriginResourcePolicyCustomizer.customize(new CrossOriginResourcePolicySpec());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures cache control headers
|
* Configures cache control headers
|
||||||
*
|
*
|
||||||
|
@ -2910,6 +3001,99 @@ public class ServerHttpSecurity {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the Cross-Origin-Opener-Policy header
|
||||||
|
*
|
||||||
|
* @since 5.7
|
||||||
|
*/
|
||||||
|
public final class CrossOriginOpenerPolicySpec {
|
||||||
|
|
||||||
|
private CrossOriginOpenerPolicySpec() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value to be used in the `Cross-Origin-Opener-Policy` header
|
||||||
|
* @param openerPolicy a opener policy
|
||||||
|
* @return the {@link CrossOriginOpenerPolicySpec} to continue configuring
|
||||||
|
*/
|
||||||
|
public CrossOriginOpenerPolicySpec policy(CrossOriginOpenerPolicy openerPolicy) {
|
||||||
|
HeaderSpec.this.crossOriginOpenerPolicy.setPolicy(openerPolicy);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows method chaining to continue configuring the
|
||||||
|
* {@link ServerHttpSecurity}.
|
||||||
|
* @return the {@link HeaderSpec} to continue configuring
|
||||||
|
*/
|
||||||
|
public HeaderSpec and() {
|
||||||
|
return HeaderSpec.this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the Cross-Origin-Embedder-Policy header
|
||||||
|
*
|
||||||
|
* @since 5.7
|
||||||
|
*/
|
||||||
|
public final class CrossOriginEmbedderPolicySpec {
|
||||||
|
|
||||||
|
private CrossOriginEmbedderPolicySpec() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value to be used in the `Cross-Origin-Embedder-Policy` header
|
||||||
|
* @param embedderPolicy a opener policy
|
||||||
|
* @return the {@link CrossOriginEmbedderPolicySpec} to continue configuring
|
||||||
|
*/
|
||||||
|
public CrossOriginEmbedderPolicySpec policy(CrossOriginEmbedderPolicy embedderPolicy) {
|
||||||
|
HeaderSpec.this.crossOriginEmbedderPolicy.setPolicy(embedderPolicy);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows method chaining to continue configuring the
|
||||||
|
* {@link ServerHttpSecurity}.
|
||||||
|
* @return the {@link HeaderSpec} to continue configuring
|
||||||
|
*/
|
||||||
|
public HeaderSpec and() {
|
||||||
|
return HeaderSpec.this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the Cross-Origin-Resource-Policy header
|
||||||
|
*
|
||||||
|
* @since 5.7
|
||||||
|
*/
|
||||||
|
public final class CrossOriginResourcePolicySpec {
|
||||||
|
|
||||||
|
private CrossOriginResourcePolicySpec() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value to be used in the `Cross-Origin-Resource-Policy` header
|
||||||
|
* @param resourcePolicy a opener policy
|
||||||
|
* @return the {@link CrossOriginResourcePolicySpec} to continue configuring
|
||||||
|
*/
|
||||||
|
public CrossOriginResourcePolicySpec policy(CrossOriginResourcePolicy resourcePolicy) {
|
||||||
|
HeaderSpec.this.crossOriginResourcePolicy.setPolicy(resourcePolicy);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows method chaining to continue configuring the
|
||||||
|
* {@link ServerHttpSecurity}.
|
||||||
|
* @return the {@link HeaderSpec} to continue configuring
|
||||||
|
*/
|
||||||
|
public HeaderSpec and() {
|
||||||
|
return HeaderSpec.this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://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.config.web.server
|
||||||
|
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||||
|
import org.springframework.security.web.server.header.CrossOriginEmbedderPolicyServerHttpHeadersWriter
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Kotlin DSL to configure the [HttpSecurity] Cross-Origin-Embedder-Policy header using
|
||||||
|
* idiomatic Kotlin code.
|
||||||
|
*
|
||||||
|
* @author Marcus Da Coregio
|
||||||
|
* @since 5.7
|
||||||
|
* @property policy the policy to be used in the response header.
|
||||||
|
*/
|
||||||
|
@ServerSecurityMarker
|
||||||
|
class ServerCrossOriginEmbedderPolicyDsl {
|
||||||
|
|
||||||
|
var policy: CrossOriginEmbedderPolicyServerHttpHeadersWriter.CrossOriginEmbedderPolicy? = null
|
||||||
|
|
||||||
|
internal fun get(): (ServerHttpSecurity.HeaderSpec.CrossOriginEmbedderPolicySpec) -> Unit {
|
||||||
|
return { crossOriginEmbedderPolicy ->
|
||||||
|
policy?.also {
|
||||||
|
crossOriginEmbedderPolicy.policy(policy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://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.config.web.server
|
||||||
|
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||||
|
import org.springframework.security.web.server.header.CrossOriginOpenerPolicyServerHttpHeadersWriter
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Kotlin DSL to configure the [HttpSecurity] Cross-Origin-Opener-Policy header using
|
||||||
|
* idiomatic Kotlin code.
|
||||||
|
*
|
||||||
|
* @author Marcus Da Coregio
|
||||||
|
* @since 5.7
|
||||||
|
* @property policy the policy to be used in the response header.
|
||||||
|
*/
|
||||||
|
@ServerSecurityMarker
|
||||||
|
class ServerCrossOriginOpenerPolicyDsl {
|
||||||
|
|
||||||
|
var policy: CrossOriginOpenerPolicyServerHttpHeadersWriter.CrossOriginOpenerPolicy? = null
|
||||||
|
|
||||||
|
internal fun get(): (ServerHttpSecurity.HeaderSpec.CrossOriginOpenerPolicySpec) -> Unit {
|
||||||
|
return { crossOriginOpenerPolicy ->
|
||||||
|
policy?.also {
|
||||||
|
crossOriginOpenerPolicy.policy(policy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://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.config.web.server
|
||||||
|
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||||
|
import org.springframework.security.web.server.header.CrossOriginResourcePolicyServerHttpHeadersWriter
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Kotlin DSL to configure the [HttpSecurity] Cross-Origin-Resource-Policy header using
|
||||||
|
* idiomatic Kotlin code.
|
||||||
|
*
|
||||||
|
* @author Marcus Da Coregio
|
||||||
|
* @since 5.7
|
||||||
|
* @property policy the policy to be used in the response header.
|
||||||
|
*/
|
||||||
|
@ServerSecurityMarker
|
||||||
|
class ServerCrossOriginResourcePolicyDsl {
|
||||||
|
|
||||||
|
var policy: CrossOriginResourcePolicyServerHttpHeadersWriter.CrossOriginResourcePolicy? = null
|
||||||
|
|
||||||
|
internal fun get(): (ServerHttpSecurity.HeaderSpec.CrossOriginResourcePolicySpec) -> Unit {
|
||||||
|
return { crossOriginResourcePolicy ->
|
||||||
|
policy?.also {
|
||||||
|
crossOriginResourcePolicy.policy(policy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,7 +16,12 @@
|
||||||
|
|
||||||
package org.springframework.security.config.web.server
|
package org.springframework.security.config.web.server
|
||||||
|
|
||||||
import org.springframework.security.web.server.header.*
|
import org.springframework.security.web.server.header.CacheControlServerHttpHeadersWriter
|
||||||
|
import org.springframework.security.web.server.header.ContentTypeOptionsServerHttpHeadersWriter
|
||||||
|
import org.springframework.security.web.server.header.ReferrerPolicyServerHttpHeadersWriter
|
||||||
|
import org.springframework.security.web.server.header.StrictTransportSecurityServerHttpHeadersWriter
|
||||||
|
import org.springframework.security.web.server.header.XFrameOptionsServerHttpHeadersWriter
|
||||||
|
import org.springframework.security.web.server.header.XXssProtectionServerHttpHeadersWriter
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Kotlin DSL to configure [ServerHttpSecurity] headers using idiomatic Kotlin code.
|
* A Kotlin DSL to configure [ServerHttpSecurity] headers using idiomatic Kotlin code.
|
||||||
|
@ -35,6 +40,9 @@ class ServerHeadersDsl {
|
||||||
private var referrerPolicy: ((ServerHttpSecurity.HeaderSpec.ReferrerPolicySpec) -> Unit)? = null
|
private var referrerPolicy: ((ServerHttpSecurity.HeaderSpec.ReferrerPolicySpec) -> Unit)? = null
|
||||||
private var featurePolicyDirectives: String? = null
|
private var featurePolicyDirectives: String? = null
|
||||||
private var permissionsPolicy: ((ServerHttpSecurity.HeaderSpec.PermissionsPolicySpec) -> Unit)? = null
|
private var permissionsPolicy: ((ServerHttpSecurity.HeaderSpec.PermissionsPolicySpec) -> Unit)? = null
|
||||||
|
private var crossOriginOpenerPolicy: ((ServerHttpSecurity.HeaderSpec.CrossOriginOpenerPolicySpec) -> Unit)? = null
|
||||||
|
private var crossOriginEmbedderPolicy: ((ServerHttpSecurity.HeaderSpec.CrossOriginEmbedderPolicySpec) -> Unit)? = null
|
||||||
|
private var crossOriginResourcePolicy: ((ServerHttpSecurity.HeaderSpec.CrossOriginResourcePolicySpec) -> Unit)? = null
|
||||||
|
|
||||||
private var disabled = false
|
private var disabled = false
|
||||||
|
|
||||||
|
@ -157,6 +165,39 @@ class ServerHeadersDsl {
|
||||||
this.permissionsPolicy = ServerPermissionsPolicyDsl().apply(permissionsPolicyConfig).get()
|
this.permissionsPolicy = ServerPermissionsPolicyDsl().apply(permissionsPolicyConfig).get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows configuration for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy">
|
||||||
|
* Cross-Origin-Opener-Policy</a> header.
|
||||||
|
*
|
||||||
|
* @since 5.7
|
||||||
|
* @param crossOriginOpenerPolicyConfig the customization to apply to the header
|
||||||
|
*/
|
||||||
|
fun crossOriginOpenerPolicy(crossOriginOpenerPolicyConfig: ServerCrossOriginOpenerPolicyDsl.() -> Unit) {
|
||||||
|
this.crossOriginOpenerPolicy = ServerCrossOriginOpenerPolicyDsl().apply(crossOriginOpenerPolicyConfig).get()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows configuration for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy">
|
||||||
|
* Cross-Origin-Embedder-Policy</a> header.
|
||||||
|
*
|
||||||
|
* @since 5.7
|
||||||
|
* @param crossOriginEmbedderPolicyConfig the customization to apply to the header
|
||||||
|
*/
|
||||||
|
fun crossOriginEmbedderPolicy(crossOriginEmbedderPolicyConfig: ServerCrossOriginEmbedderPolicyDsl.() -> Unit) {
|
||||||
|
this.crossOriginEmbedderPolicy = ServerCrossOriginEmbedderPolicyDsl().apply(crossOriginEmbedderPolicyConfig).get()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows configuration for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy">
|
||||||
|
* Cross-Origin-Resource-Policy</a> header.
|
||||||
|
*
|
||||||
|
* @since 5.7
|
||||||
|
* @param crossOriginResourcePolicyConfig the customization to apply to the header
|
||||||
|
*/
|
||||||
|
fun crossOriginResourcePolicy(crossOriginResourcePolicyConfig: ServerCrossOriginResourcePolicyDsl.() -> Unit) {
|
||||||
|
this.crossOriginResourcePolicy = ServerCrossOriginResourcePolicyDsl().apply(crossOriginResourcePolicyConfig).get()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disables HTTP response headers.
|
* Disables HTTP response headers.
|
||||||
*/
|
*/
|
||||||
|
@ -194,6 +235,15 @@ class ServerHeadersDsl {
|
||||||
referrerPolicy?.also {
|
referrerPolicy?.also {
|
||||||
headers.referrerPolicy(referrerPolicy)
|
headers.referrerPolicy(referrerPolicy)
|
||||||
}
|
}
|
||||||
|
crossOriginOpenerPolicy?.also {
|
||||||
|
headers.crossOriginOpenerPolicy(crossOriginOpenerPolicy)
|
||||||
|
}
|
||||||
|
crossOriginEmbedderPolicy?.also {
|
||||||
|
headers.crossOriginEmbedderPolicy(crossOriginEmbedderPolicy)
|
||||||
|
}
|
||||||
|
crossOriginResourcePolicy?.also {
|
||||||
|
headers.crossOriginResourcePolicy(crossOriginResourcePolicy)
|
||||||
|
}
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
headers.disable()
|
headers.disable()
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,9 @@ class HeadersDsl {
|
||||||
private var referrerPolicy: ((HeadersConfigurer<HttpSecurity>.ReferrerPolicyConfig) -> Unit)? = null
|
private var referrerPolicy: ((HeadersConfigurer<HttpSecurity>.ReferrerPolicyConfig) -> Unit)? = null
|
||||||
private var featurePolicyDirectives: String? = null
|
private var featurePolicyDirectives: String? = null
|
||||||
private var permissionsPolicy: ((HeadersConfigurer<HttpSecurity>.PermissionsPolicyConfig) -> Unit)? = null
|
private var permissionsPolicy: ((HeadersConfigurer<HttpSecurity>.PermissionsPolicyConfig) -> Unit)? = null
|
||||||
|
private var crossOriginOpenerPolicy: ((HeadersConfigurer<HttpSecurity>.CrossOriginOpenerPolicyConfig) -> Unit)? = null
|
||||||
|
private var crossOriginEmbedderPolicy: ((HeadersConfigurer<HttpSecurity>.CrossOriginEmbedderPolicyConfig) -> Unit)? = null
|
||||||
|
private var crossOriginResourcePolicy: ((HeadersConfigurer<HttpSecurity>.CrossOriginResourcePolicyConfig) -> Unit)? = null
|
||||||
private var disabled = false
|
private var disabled = false
|
||||||
private var headerWriters = mutableListOf<HeaderWriter>()
|
private var headerWriters = mutableListOf<HeaderWriter>()
|
||||||
|
|
||||||
|
@ -181,6 +184,54 @@ class HeadersDsl {
|
||||||
this.permissionsPolicy = PermissionsPolicyDsl().apply(permissionsPolicyConfig).get()
|
this.permissionsPolicy = PermissionsPolicyDsl().apply(permissionsPolicyConfig).get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows configuration for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy">
|
||||||
|
* Cross-Origin-Opener-Policy</a> header.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Calling this method automatically enables (includes) the Cross-Origin-Opener-Policy
|
||||||
|
* header in the response using the supplied policy.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* @since 5.7
|
||||||
|
* @param crossOriginOpenerPolicyConfig the customization to apply to the header
|
||||||
|
*/
|
||||||
|
fun crossOriginOpenerPolicy(crossOriginOpenerPolicyConfig: CrossOriginOpenerPolicyDsl.() -> Unit) {
|
||||||
|
this.crossOriginOpenerPolicy = CrossOriginOpenerPolicyDsl().apply(crossOriginOpenerPolicyConfig).get()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows configuration for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy">
|
||||||
|
* Cross-Origin-Embedder-Policy</a> header.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Calling this method automatically enables (includes) the Cross-Origin-Embedder-Policy
|
||||||
|
* header in the response using the supplied policy.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* @since 5.7
|
||||||
|
* @param crossOriginEmbedderPolicyConfig the customization to apply to the header
|
||||||
|
*/
|
||||||
|
fun crossOriginEmbedderPolicy(crossOriginEmbedderPolicyConfig: CrossOriginEmbedderPolicyDsl.() -> Unit) {
|
||||||
|
this.crossOriginEmbedderPolicy = CrossOriginEmbedderPolicyDsl().apply(crossOriginEmbedderPolicyConfig).get()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy">
|
||||||
|
* Cross-Origin-Resource-Policy</a> header.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Calling this method automatically enables (includes) the Cross-Origin-Resource-Policy
|
||||||
|
* header in the response using the supplied policy.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* @since 5.7
|
||||||
|
* @param crossOriginResourcePolicyConfig the customization to apply to the header
|
||||||
|
*/
|
||||||
|
fun crossOriginResourcePolicy(crossOriginResourcePolicyConfig: CrossOriginResourcePolicyDsl.() -> Unit) {
|
||||||
|
this.crossOriginResourcePolicy = CrossOriginResourcePolicyDsl().apply(crossOriginResourcePolicyConfig).get()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a [HeaderWriter] instance.
|
* Adds a [HeaderWriter] instance.
|
||||||
*
|
*
|
||||||
|
@ -238,6 +289,15 @@ class HeadersDsl {
|
||||||
permissionsPolicy?.also {
|
permissionsPolicy?.also {
|
||||||
headers.permissionsPolicy(permissionsPolicy)
|
headers.permissionsPolicy(permissionsPolicy)
|
||||||
}
|
}
|
||||||
|
crossOriginOpenerPolicy?.also {
|
||||||
|
headers.crossOriginOpenerPolicy(crossOriginOpenerPolicy)
|
||||||
|
}
|
||||||
|
crossOriginEmbedderPolicy?.also {
|
||||||
|
headers.crossOriginEmbedderPolicy(crossOriginEmbedderPolicy)
|
||||||
|
}
|
||||||
|
crossOriginResourcePolicy?.also {
|
||||||
|
headers.crossOriginResourcePolicy(crossOriginResourcePolicy)
|
||||||
|
}
|
||||||
headerWriters.forEach { headerWriter ->
|
headerWriters.forEach { headerWriter ->
|
||||||
headers.addHeaderWriter(headerWriter)
|
headers.addHeaderWriter(headerWriter)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://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.config.web.servlet.headers
|
||||||
|
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||||
|
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer
|
||||||
|
import org.springframework.security.web.header.writers.CrossOriginEmbedderPolicyHeaderWriter
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Kotlin DSL to configure the [HttpSecurity] Cross-Origin-Embedder-Policy header using
|
||||||
|
* idiomatic Kotlin code.
|
||||||
|
*
|
||||||
|
* @author Marcus Da Coregio
|
||||||
|
* @since 5.7
|
||||||
|
* @property policy the policy to be used in the response header.
|
||||||
|
*/
|
||||||
|
@HeadersSecurityMarker
|
||||||
|
class CrossOriginEmbedderPolicyDsl {
|
||||||
|
|
||||||
|
var policy: CrossOriginEmbedderPolicyHeaderWriter.CrossOriginEmbedderPolicy? = null
|
||||||
|
|
||||||
|
internal fun get(): (HeadersConfigurer<HttpSecurity>.CrossOriginEmbedderPolicyConfig) -> Unit {
|
||||||
|
return { crossOriginEmbedderPolicy ->
|
||||||
|
policy?.also {
|
||||||
|
crossOriginEmbedderPolicy.policy(policy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://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.config.web.servlet.headers
|
||||||
|
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||||
|
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer
|
||||||
|
import org.springframework.security.web.header.writers.CrossOriginOpenerPolicyHeaderWriter
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Kotlin DSL to configure the [HttpSecurity] Cross-Origin-Opener-Policy header using
|
||||||
|
* idiomatic Kotlin code.
|
||||||
|
*
|
||||||
|
* @author Marcus Da Coregio
|
||||||
|
* @since 5.7
|
||||||
|
* @property policy the policy to be used in the response header.
|
||||||
|
*/
|
||||||
|
@HeadersSecurityMarker
|
||||||
|
class CrossOriginOpenerPolicyDsl {
|
||||||
|
|
||||||
|
var policy: CrossOriginOpenerPolicyHeaderWriter.CrossOriginOpenerPolicy? = null
|
||||||
|
|
||||||
|
internal fun get(): (HeadersConfigurer<HttpSecurity>.CrossOriginOpenerPolicyConfig) -> Unit {
|
||||||
|
return { crossOriginOpenerPolicy ->
|
||||||
|
policy?.also {
|
||||||
|
crossOriginOpenerPolicy.policy(policy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://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.config.web.servlet.headers
|
||||||
|
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||||
|
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer
|
||||||
|
import org.springframework.security.web.header.writers.CrossOriginResourcePolicyHeaderWriter
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Kotlin DSL to configure the [HttpSecurity] Cross-Origin-Resource-Policy header using
|
||||||
|
* idiomatic Kotlin code.
|
||||||
|
*
|
||||||
|
* @author Marcus Da Coregio
|
||||||
|
* @since 5.7
|
||||||
|
* @property policy the policy to be used in the response header.
|
||||||
|
*/
|
||||||
|
@HeadersSecurityMarker
|
||||||
|
class CrossOriginResourcePolicyDsl {
|
||||||
|
|
||||||
|
var policy: CrossOriginResourcePolicyHeaderWriter.CrossOriginResourcePolicy? = null
|
||||||
|
|
||||||
|
internal fun get(): (HeadersConfigurer<HttpSecurity>.CrossOriginResourcePolicyConfig) -> Unit {
|
||||||
|
return { crossOriginResourcePolicy ->
|
||||||
|
policy?.also {
|
||||||
|
crossOriginResourcePolicy.policy(policy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -943,7 +943,7 @@ csrf-options.attlist &=
|
||||||
|
|
||||||
headers =
|
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 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? & feature-policy? & permissions-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? & permissions-policy? & cross-origin-opener-policy? & cross-origin-embedder-policy? & cross-origin-resource-policy? & header*)}
|
||||||
headers-options.attlist &=
|
headers-options.attlist &=
|
||||||
## Specifies if the default headers should be disabled. Default false.
|
## Specifies if the default headers should be disabled. Default false.
|
||||||
attribute defaults-disabled {xsd:token}?
|
attribute defaults-disabled {xsd:token}?
|
||||||
|
@ -1092,6 +1092,27 @@ content-type-options.attlist &=
|
||||||
## If disabled, the X-Content-Type-Options header will not be included. Default false.
|
## If disabled, the X-Content-Type-Options header will not be included. Default false.
|
||||||
attribute disabled {xsd:boolean}?
|
attribute disabled {xsd:boolean}?
|
||||||
|
|
||||||
|
cross-origin-opener-policy =
|
||||||
|
## Adds support for Cross-Origin-Opener-Policy header
|
||||||
|
element cross-origin-opener-policy {cross-origin-opener-policy-options.attlist,empty}
|
||||||
|
cross-origin-opener-policy-options.attlist &=
|
||||||
|
## The policies for the Cross-Origin-Opener-Policy header.
|
||||||
|
attribute policy {"unsafe-none","same-origin","same-origin-allow-popups"}?
|
||||||
|
|
||||||
|
cross-origin-embedder-policy =
|
||||||
|
## Adds support for Cross-Origin-Embedder-Policy header
|
||||||
|
element cross-origin-embedder-policy {cross-origin-embedder-policy-options.attlist,empty}
|
||||||
|
cross-origin-embedder-policy-options.attlist &=
|
||||||
|
## The policies for the Cross-Origin-Embedder-Policy header.
|
||||||
|
attribute policy {"unsafe-none","require-corp"}?
|
||||||
|
|
||||||
|
cross-origin-resource-policy =
|
||||||
|
## Adds support for Cross-Origin-Resource-Policy header
|
||||||
|
element cross-origin-resource-policy {cross-origin-resource-policy-options.attlist,empty}
|
||||||
|
cross-origin-resource-policy-options.attlist &=
|
||||||
|
## The policies for the Cross-Origin-Resource-Policy header.
|
||||||
|
attribute policy {"cross-origin","same-origin","same-site"}?
|
||||||
|
|
||||||
header=
|
header=
|
||||||
## Add additional headers to the response.
|
## Add additional headers to the response.
|
||||||
element header {header.attlist}
|
element header {header.attlist}
|
||||||
|
|
|
@ -2768,6 +2768,9 @@
|
||||||
<xs:element ref="security:referrer-policy"/>
|
<xs:element ref="security:referrer-policy"/>
|
||||||
<xs:element ref="security:feature-policy"/>
|
<xs:element ref="security:feature-policy"/>
|
||||||
<xs:element ref="security:permissions-policy"/>
|
<xs:element ref="security:permissions-policy"/>
|
||||||
|
<xs:element ref="security:cross-origin-opener-policy"/>
|
||||||
|
<xs:element ref="security:cross-origin-embedder-policy"/>
|
||||||
|
<xs:element ref="security:cross-origin-resource-policy"/>
|
||||||
<xs:element ref="security:header"/>
|
<xs:element ref="security:header"/>
|
||||||
</xs:choice>
|
</xs:choice>
|
||||||
<xs:attributeGroup ref="security:headers-options.attlist"/>
|
<xs:attributeGroup ref="security:headers-options.attlist"/>
|
||||||
|
@ -3151,6 +3154,77 @@
|
||||||
</xs:annotation>
|
</xs:annotation>
|
||||||
</xs:attribute>
|
</xs:attribute>
|
||||||
</xs:attributeGroup>
|
</xs:attributeGroup>
|
||||||
|
<xs:element name="cross-origin-opener-policy">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>Adds support for Cross-Origin-Opener-Policy header
|
||||||
|
</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:attributeGroup ref="security:cross-origin-opener-policy-options.attlist"/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
<xs:attributeGroup name="cross-origin-opener-policy-options.attlist">
|
||||||
|
<xs:attribute name="policy">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>The policies for the Cross-Origin-Opener-Policy header.
|
||||||
|
</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
<xs:simpleType>
|
||||||
|
<xs:restriction base="xs:token">
|
||||||
|
<xs:enumeration value="unsafe-none"/>
|
||||||
|
<xs:enumeration value="same-origin"/>
|
||||||
|
<xs:enumeration value="same-origin-allow-popups"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
</xs:attribute>
|
||||||
|
</xs:attributeGroup>
|
||||||
|
<xs:element name="cross-origin-embedder-policy">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>Adds support for Cross-Origin-Embedder-Policy header
|
||||||
|
</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:attributeGroup ref="security:cross-origin-embedder-policy-options.attlist"/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
<xs:attributeGroup name="cross-origin-embedder-policy-options.attlist">
|
||||||
|
<xs:attribute name="policy">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>The policies for the Cross-Origin-Embedder-Policy header.
|
||||||
|
</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
<xs:simpleType>
|
||||||
|
<xs:restriction base="xs:token">
|
||||||
|
<xs:enumeration value="unsafe-none"/>
|
||||||
|
<xs:enumeration value="require-corp"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
</xs:attribute>
|
||||||
|
</xs:attributeGroup>
|
||||||
|
<xs:element name="cross-origin-resource-policy">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>Adds support for Cross-Origin-Resource-Policy header
|
||||||
|
</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:attributeGroup ref="security:cross-origin-resource-policy-options.attlist"/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
<xs:attributeGroup name="cross-origin-resource-policy-options.attlist">
|
||||||
|
<xs:attribute name="policy">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>The policies for the Cross-Origin-Resource-Policy header.
|
||||||
|
</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
<xs:simpleType>
|
||||||
|
<xs:restriction base="xs:token">
|
||||||
|
<xs:enumeration value="cross-origin"/>
|
||||||
|
<xs:enumeration value="same-origin"/>
|
||||||
|
<xs:enumeration value="same-site"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
</xs:attribute>
|
||||||
|
</xs:attributeGroup>
|
||||||
<xs:element name="header">
|
<xs:element name="header">
|
||||||
<xs:annotation>
|
<xs:annotation>
|
||||||
<xs:documentation>Add additional headers to the response.
|
<xs:documentation>Add additional headers to the response.
|
||||||
|
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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.BeanCreationException;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
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.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
import org.springframework.security.config.test.SpringTestContext;
|
import org.springframework.security.config.test.SpringTestContext;
|
||||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
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.ReferrerPolicyHeaderWriter.ReferrerPolicy;
|
||||||
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter.XFrameOptionsMode;
|
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter.XFrameOptionsMode;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
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 Eddú Meléndez
|
||||||
* @author Vedran Pavic
|
* @author Vedran Pavic
|
||||||
* @author Eleftheria Stein
|
* @author Eleftheria Stein
|
||||||
|
* @author Marcus Da Coregio
|
||||||
*/
|
*/
|
||||||
@ExtendWith(SpringTestContextExtension.class)
|
@ExtendWith(SpringTestContextExtension.class)
|
||||||
public class HeadersConfigurerTests {
|
public class HeadersConfigurerTests {
|
||||||
|
@ -514,6 +520,30 @@ public class HeadersConfigurerTests {
|
||||||
assertThat(mvcResult.getResponse().getHeaderNames()).containsExactly(HttpHeaders.STRICT_TRANSPORT_SECURITY);
|
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
|
@EnableWebSecurity
|
||||||
static class HeadersConfig extends WebSecurityConfigurerAdapter {
|
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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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 Tim Ysewyn
|
||||||
* @author Josh Cummings
|
* @author Josh Cummings
|
||||||
* @author Rafiullah Hamedy
|
* @author Rafiullah Hamedy
|
||||||
|
* @author Marcus Da Coregio
|
||||||
*/
|
*/
|
||||||
@ExtendWith(SpringTestContextExtension.class)
|
@ExtendWith(SpringTestContextExtension.class)
|
||||||
public class HttpHeadersConfigTests {
|
public class HttpHeadersConfigTests {
|
||||||
|
@ -733,6 +734,53 @@ public class HttpHeadersConfigTests {
|
||||||
// @formatter:on
|
// @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() {
|
private static ResultMatcher includesDefaults() {
|
||||||
return includes(defaultHeaders);
|
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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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.test.web.reactive.server.WebTestClientBuilder;
|
||||||
import org.springframework.security.web.server.header.ContentSecurityPolicyServerHttpHeadersWriter;
|
import org.springframework.security.web.server.header.ContentSecurityPolicyServerHttpHeadersWriter;
|
||||||
import org.springframework.security.web.server.header.ContentTypeOptionsServerHttpHeadersWriter;
|
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.FeaturePolicyServerHttpHeadersWriter;
|
||||||
import org.springframework.security.web.server.header.ReferrerPolicyServerHttpHeadersWriter;
|
import org.springframework.security.web.server.header.ReferrerPolicyServerHttpHeadersWriter;
|
||||||
import org.springframework.security.web.server.header.ReferrerPolicyServerHttpHeadersWriter.ReferrerPolicy;
|
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 Rob Winch
|
||||||
* @author Vedran Pavic
|
* @author Vedran Pavic
|
||||||
* @author Ankur Pathak
|
* @author Ankur Pathak
|
||||||
|
* @author Marcus Da Coregio
|
||||||
* @since 5.0
|
* @since 5.0
|
||||||
*/
|
*/
|
||||||
public class HeaderSpecTests {
|
public class HeaderSpecTests {
|
||||||
|
@ -406,6 +410,53 @@ public class HeaderSpecTests {
|
||||||
assertHeaders();
|
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) {
|
private void expectHeaderNamesNotPresent(String... headerNames) {
|
||||||
for (String headerName : headerNames) {
|
for (String headerName : headerNames) {
|
||||||
this.expectedHeaders.remove(headerName);
|
this.expectedHeaders.remove(headerName);
|
||||||
|
|
|
@ -28,6 +28,9 @@ import org.springframework.security.config.test.SpringTestContextExtension
|
||||||
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter
|
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter
|
||||||
import org.springframework.security.web.server.SecurityWebFilterChain
|
import org.springframework.security.web.server.SecurityWebFilterChain
|
||||||
import org.springframework.security.web.server.header.ContentTypeOptionsServerHttpHeadersWriter
|
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.StrictTransportSecurityServerHttpHeadersWriter
|
import org.springframework.security.web.server.header.StrictTransportSecurityServerHttpHeadersWriter
|
||||||
import org.springframework.security.web.server.header.XFrameOptionsServerHttpHeadersWriter
|
import org.springframework.security.web.server.header.XFrameOptionsServerHttpHeadersWriter
|
||||||
import org.springframework.security.web.server.header.XXssProtectionServerHttpHeadersWriter
|
import org.springframework.security.web.server.header.XXssProtectionServerHttpHeadersWriter
|
||||||
|
@ -133,4 +136,60 @@ class ServerHeadersDslTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `request when no cross-origin policies configured then does not write cross-origin policies headers in response`() {
|
||||||
|
this.spring.register(CrossOriginPoliciesConfig::class.java).autowire()
|
||||||
|
|
||||||
|
this.client.get()
|
||||||
|
.uri("/")
|
||||||
|
.exchange()
|
||||||
|
.expectHeader().doesNotExist("Cross-Origin-Opener-Policy")
|
||||||
|
.expectHeader().doesNotExist("Cross-Origin-Embedder-Policy")
|
||||||
|
.expectHeader().doesNotExist("Cross-Origin-Resource-Policy")
|
||||||
|
}
|
||||||
|
|
||||||
|
@EnableWebFluxSecurity
|
||||||
|
@EnableWebFlux
|
||||||
|
open class CrossOriginPoliciesConfig {
|
||||||
|
@Bean
|
||||||
|
open fun springWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
|
||||||
|
return http {
|
||||||
|
headers { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `request when cross-origin custom policies configured then cross-origin custom policies headers in response`() {
|
||||||
|
this.spring.register(CrossOriginPoliciesCustomConfig::class.java).autowire()
|
||||||
|
|
||||||
|
this.client.get()
|
||||||
|
.uri("/")
|
||||||
|
.exchange()
|
||||||
|
.expectHeader().valueEquals("Cross-Origin-Opener-Policy", "same-origin")
|
||||||
|
.expectHeader().valueEquals("Cross-Origin-Embedder-Policy", "require-corp")
|
||||||
|
.expectHeader().valueEquals("Cross-Origin-Resource-Policy", "same-origin")
|
||||||
|
}
|
||||||
|
|
||||||
|
@EnableWebFluxSecurity
|
||||||
|
@EnableWebFlux
|
||||||
|
open class CrossOriginPoliciesCustomConfig {
|
||||||
|
@Bean
|
||||||
|
open fun springWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
|
||||||
|
return http {
|
||||||
|
headers {
|
||||||
|
crossOriginOpenerPolicy {
|
||||||
|
policy = CrossOriginOpenerPolicyServerHttpHeadersWriter.CrossOriginOpenerPolicy.SAME_ORIGIN
|
||||||
|
}
|
||||||
|
crossOriginEmbedderPolicy {
|
||||||
|
policy = CrossOriginEmbedderPolicyServerHttpHeadersWriter.CrossOriginEmbedderPolicy.REQUIRE_CORP
|
||||||
|
}
|
||||||
|
crossOriginResourcePolicy {
|
||||||
|
policy = CrossOriginResourcePolicyServerHttpHeadersWriter.CrossOriginResourcePolicy.SAME_ORIGIN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,13 +19,13 @@ package org.springframework.security.config.web.servlet
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.extension.ExtendWith
|
import org.junit.jupiter.api.extension.ExtendWith
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
|
import org.springframework.context.annotation.Bean
|
||||||
import org.springframework.http.HttpHeaders
|
import org.springframework.http.HttpHeaders
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
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.EnableWebSecurity
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
|
||||||
import org.springframework.security.config.test.SpringTestContext
|
import org.springframework.security.config.test.SpringTestContext
|
||||||
import org.springframework.security.config.test.SpringTestContextExtension
|
import org.springframework.security.config.test.SpringTestContextExtension
|
||||||
import org.springframework.security.config.web.servlet.headers.PermissionsPolicyDsl
|
|
||||||
import org.springframework.security.web.header.writers.StaticHeadersWriter
|
import org.springframework.security.web.header.writers.StaticHeadersWriter
|
||||||
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter
|
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter
|
||||||
import org.springframework.security.web.server.header.ContentTypeOptionsServerHttpHeadersWriter
|
import org.springframework.security.web.server.header.ContentTypeOptionsServerHttpHeadersWriter
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ 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.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ https://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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://www.springframework.org/schema/security"
|
||||||
|
xsi:schemaLocation="
|
||||||
|
http://www.springframework.org/schema/security
|
||||||
|
https://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans
|
||||||
|
https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||||
|
|
||||||
|
<http auto-config="true">
|
||||||
|
<headers defaults-disabled="true">
|
||||||
|
<cross-origin-embedder-policy policy="require-corp"/>
|
||||||
|
</headers>
|
||||||
|
</http>
|
||||||
|
|
||||||
|
<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>
|
||||||
|
|
||||||
|
<b:import resource="userservice.xml"/>
|
||||||
|
</b:beans>
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ 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.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ https://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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://www.springframework.org/schema/security"
|
||||||
|
xsi:schemaLocation="
|
||||||
|
http://www.springframework.org/schema/security
|
||||||
|
https://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans
|
||||||
|
https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||||
|
|
||||||
|
<http auto-config="true">
|
||||||
|
<headers defaults-disabled="true">
|
||||||
|
<cross-origin-opener-policy policy="same-origin-allow-popups"/>
|
||||||
|
</headers>
|
||||||
|
</http>
|
||||||
|
|
||||||
|
<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>
|
||||||
|
|
||||||
|
<b:import resource="userservice.xml"/>
|
||||||
|
</b:beans>
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ 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.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ https://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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://www.springframework.org/schema/security"
|
||||||
|
xsi:schemaLocation="
|
||||||
|
http://www.springframework.org/schema/security
|
||||||
|
https://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans
|
||||||
|
https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||||
|
|
||||||
|
<http auto-config="true">
|
||||||
|
<headers defaults-disabled="true">
|
||||||
|
<cross-origin-opener-policy policy="same-origin"/>
|
||||||
|
<cross-origin-embedder-policy policy="require-corp"/>
|
||||||
|
<cross-origin-resource-policy policy="same-origin"/>
|
||||||
|
</headers>
|
||||||
|
</http>
|
||||||
|
|
||||||
|
<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>
|
||||||
|
|
||||||
|
<b:import resource="userservice.xml"/>
|
||||||
|
</b:beans>
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ 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.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ https://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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://www.springframework.org/schema/security"
|
||||||
|
xsi:schemaLocation="
|
||||||
|
http://www.springframework.org/schema/security
|
||||||
|
https://www.springframework.org/schema/security/spring-security.xsd
|
||||||
|
http://www.springframework.org/schema/beans
|
||||||
|
https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||||
|
|
||||||
|
<http auto-config="true">
|
||||||
|
<headers defaults-disabled="true">
|
||||||
|
<cross-origin-resource-policy policy="same-origin"/>
|
||||||
|
</headers>
|
||||||
|
</http>
|
||||||
|
|
||||||
|
<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>
|
||||||
|
|
||||||
|
<b:import resource="userservice.xml"/>
|
||||||
|
</b:beans>
|
|
@ -378,6 +378,26 @@ Clear-Site-Data: "cache", "cookies", "storage", "executionContexts"
|
||||||
|
|
||||||
This is a nice clean-up action to perform on logout.
|
This is a nice clean-up action to perform on logout.
|
||||||
|
|
||||||
|
[[headers-cross-origin-policies]]
|
||||||
|
== Cross-Origin Policies
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
====
|
||||||
|
Refer to the relevant sections to see how to configure for both <<servlet-headers-cross-origin-policies,servlet>> and <<webflux-headers-cross-origin-policies,webflux>> based applications.
|
||||||
|
====
|
||||||
|
|
||||||
|
Spring Security provides support for some important Cross-Origin Policies headers.
|
||||||
|
Those headers are:
|
||||||
|
|
||||||
|
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy[`Cross-Origin-Opener-Policy`]
|
||||||
|
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy[`Cross-Origin-Embedder-Policy`]
|
||||||
|
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy[`Cross-Origin-Resource-Policy`]
|
||||||
|
|
||||||
|
`Cross-Origin-Opener-Policy` (COOP) allows a top-level document to break the association between its window and any others in the browsing context group (e.g., between a popup and its opener), preventing any direct DOM access between them.
|
||||||
|
|
||||||
|
Enabling `Cross-Origin-Embedder-Policy` (COEP) prevents a document from loading any non-same-origin resources which don't explicitly grant the document permission to be loaded.
|
||||||
|
|
||||||
|
The `Cross-Origin-Resource-Policy` (CORP) header allows you to control the set of origins that are empowered to include a resource. It is a robust defense against attacks like https://meltdownattack.com[Spectre], as it allows browsers to block a given response before it enters an attacker's process.
|
||||||
|
|
||||||
[[headers-custom]]
|
[[headers-custom]]
|
||||||
== Custom Headers
|
== Custom Headers
|
||||||
|
|
|
@ -578,3 +578,65 @@ fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
|
[[webflux-headers-cross-origin-policies]]
|
||||||
|
== Cross-Origin Policies
|
||||||
|
|
||||||
|
Spring Security provides built-in support for adding some Cross-Origin policies headers, those headers are:
|
||||||
|
|
||||||
|
[source]
|
||||||
|
----
|
||||||
|
Cross-Origin-Opener-Policy
|
||||||
|
Cross-Origin-Embedder-Policy
|
||||||
|
Cross-Origin-Resource-Policy
|
||||||
|
----
|
||||||
|
|
||||||
|
Spring Security does not add <<headers-cross-origin-policies,Cross-Origin Policies>> headers by default.
|
||||||
|
The headers can be added with the following configuration:
|
||||||
|
|
||||||
|
.Cross-Origin Policies
|
||||||
|
====
|
||||||
|
.Java
|
||||||
|
[source,java,role="primary"]
|
||||||
|
----
|
||||||
|
@EnableWebFluxSecurity
|
||||||
|
@EnableWebFlux
|
||||||
|
public class WebSecurityConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
SecurityWebFilterChain securityFilterChain(ServerHttpSecurity http) {
|
||||||
|
http.headers((headers) -> headers
|
||||||
|
.crossOriginOpenerPolicy(CrossOriginOpenerPolicy.SAME_ORIGIN)
|
||||||
|
.crossOriginEmbedderPolicy(CrossOriginEmbedderPolicy.REQUIRE_CORP)
|
||||||
|
.crossOriginResourcePolicy(CrossOriginResourcePolicy.SAME_ORIGIN));
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
----
|
||||||
|
.Kotlin
|
||||||
|
[source,kotlin,role="secondary"]
|
||||||
|
----
|
||||||
|
@EnableWebFluxSecurity
|
||||||
|
@EnableWebFlux
|
||||||
|
open class CrossOriginPoliciesCustomConfig {
|
||||||
|
@Bean
|
||||||
|
open fun springWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
|
||||||
|
return http {
|
||||||
|
headers {
|
||||||
|
crossOriginOpenerPolicy(CrossOriginOpenerPolicy.SAME_ORIGIN)
|
||||||
|
crossOriginEmbedderPolicy(CrossOriginEmbedderPolicy.REQUIRE_CORP)
|
||||||
|
crossOriginResourcePolicy(CrossOriginResourcePolicy.SAME_ORIGIN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
This configuration will write the headers with the values provided:
|
||||||
|
[source]
|
||||||
|
----
|
||||||
|
Cross-Origin-Opener-Policy: same-origin
|
||||||
|
Cross-Origin-Embedder-Policy: require-corp
|
||||||
|
Cross-Origin-Resource-Policy: same-origin
|
||||||
|
----
|
||||||
|
|
|
@ -238,6 +238,9 @@ This allows HTTPS websites to resist impersonation by attackers using mis-issued
|
||||||
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).
|
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.
|
** `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.
|
** `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.
|
||||||
|
** `Cross-Origin-Opener-Policy` - Can be set using the <<nsa-cross-origin-opener-policy,cross-origin-opener-policy>> element, https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy[Cross-Origin-Opener-Policy] is a mechanism that allows you to ensure a top-level document does not share a browsing context group with cross-origin documents.
|
||||||
|
** `Cross-Origin-Embedder-Policy` - Can be set using the <<nsa-cross-origin-embedder-policy,cross-origin-embedder-policy>> element, https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy[Cross-Origin-Embedder-Policy] is a mechanism that prevents a document from loading any cross-origin resources that don't explicitly grant the document permission.
|
||||||
|
** `Cross-Origin-Resource-Policy` - Can be set using the <<nsa-cross-origin-resource-policy,cross-origin-resource-policy>> element, https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy[Cross-Origin-Resource-Policy] is a mechanism that conveys a desire that the browser blocks no-cors cross-origin/cross-site requests to the given resource.
|
||||||
|
|
||||||
[[nsa-headers-attributes]]
|
[[nsa-headers-attributes]]
|
||||||
=== <headers> Attributes
|
=== <headers> Attributes
|
||||||
|
@ -269,6 +272,9 @@ The default is false (the headers are enabled).
|
||||||
* <<nsa-cache-control,cache-control>>
|
* <<nsa-cache-control,cache-control>>
|
||||||
* <<nsa-content-security-policy,content-security-policy>>
|
* <<nsa-content-security-policy,content-security-policy>>
|
||||||
* <<nsa-content-type-options,content-type-options>>
|
* <<nsa-content-type-options,content-type-options>>
|
||||||
|
* <<nsa-cross-origin-embedder-policy,cross-origin-embedder-policy>>
|
||||||
|
* <<nsa-cross-origin-opener-policy,cross-origin-opener-policy>>
|
||||||
|
* <<nsa-cross-origin-resource-policy,cross-origin-resource-policy>>
|
||||||
* <<nsa-feature-policy,feature-policy>>
|
* <<nsa-feature-policy,feature-policy>>
|
||||||
* <<nsa-frame-options,frame-options>>
|
* <<nsa-frame-options,frame-options>>
|
||||||
* <<nsa-header,header>>
|
* <<nsa-header,header>>
|
||||||
|
@ -584,6 +590,66 @@ Default false.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[nsa-cross-origin-embedder-policy]]
|
||||||
|
==== <cross-origin-embedder-policy>
|
||||||
|
When enabled adds the https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy[Cross-Origin-Embedder-Policy] header to the response.
|
||||||
|
|
||||||
|
|
||||||
|
[[nsa-cross-origin-embedder-policy-attributes]]
|
||||||
|
===== <cross-origin-embedder-policy> Attributes
|
||||||
|
|
||||||
|
[[nsa-cross-origin-embedder-policy-policy]]
|
||||||
|
* **policy**
|
||||||
|
The policy for the `Cross-Origin-Embedder-Policy` header.
|
||||||
|
|
||||||
|
[[nsa-cross-origin-embedder-policy-parents]]
|
||||||
|
===== Parent Elements of <cross-origin-embedder-policy>
|
||||||
|
|
||||||
|
|
||||||
|
* <<nsa-headers,headers>>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[nsa-cross-origin-opener-policy]]
|
||||||
|
==== <cross-origin-opener-policy>
|
||||||
|
When enabled adds the https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy[Cross-Origin-Opener-Policy] header to the response.
|
||||||
|
|
||||||
|
|
||||||
|
[[nsa-cross-origin-opener-policy-attributes]]
|
||||||
|
===== <cross-origin-opener-policy> Attributes
|
||||||
|
|
||||||
|
[[nsa-cross-origin-opener-policy-policy]]
|
||||||
|
* **policy**
|
||||||
|
The policy for the `Cross-Origin-Opener-Policy` header.
|
||||||
|
|
||||||
|
[[nsa-cross-origin-opener-policy-parents]]
|
||||||
|
===== Parent Elements of <cross-origin-opener-policy>
|
||||||
|
|
||||||
|
|
||||||
|
* <<nsa-headers,headers>>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[nsa-cross-origin-resource-policy]]
|
||||||
|
==== <cross-origin-resource-policy>
|
||||||
|
When enabled adds the https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy[Cross-Origin-Resource-Policy] header to the response.
|
||||||
|
|
||||||
|
|
||||||
|
[[nsa-cross-origin-resource-policy-attributes]]
|
||||||
|
===== <cross-origin-resource-policy> Attributes
|
||||||
|
|
||||||
|
[[nsa-cross-origin-resource-policy-policy]]
|
||||||
|
* **policy**
|
||||||
|
The policy for the `Cross-Origin-Resource-Policy` header.
|
||||||
|
|
||||||
|
[[nsa-cross-origin-resource-policy-parents]]
|
||||||
|
===== Parent Elements of <cross-origin-resource-policy>
|
||||||
|
|
||||||
|
|
||||||
|
* <<nsa-headers,headers>>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[[nsa-header]]
|
[[nsa-header]]
|
||||||
== <header>
|
== <header>
|
||||||
Add additional headers to the response, both the name and value need to be specified.
|
Add additional headers to the response, both the name and value need to be specified.
|
||||||
|
|
|
@ -938,6 +938,67 @@ class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
|
[[servlet-headers-cross-origin-policies]]
|
||||||
|
== Cross-Origin Policies
|
||||||
|
|
||||||
|
Spring Security provides built-in support for adding some Cross-Origin policies headers, those headers are:
|
||||||
|
|
||||||
|
[source]
|
||||||
|
----
|
||||||
|
Cross-Origin-Opener-Policy
|
||||||
|
Cross-Origin-Embedder-Policy
|
||||||
|
Cross-Origin-Resource-Policy
|
||||||
|
----
|
||||||
|
|
||||||
|
Spring Security does not add <<headers-cross-origin-policies,Cross-Origin Policies>> headers by default.
|
||||||
|
The headers can be added with the following configuration:
|
||||||
|
|
||||||
|
.Cross-Origin Policies
|
||||||
|
====
|
||||||
|
.Java
|
||||||
|
[source,java,role="primary"]
|
||||||
|
----
|
||||||
|
@EnableWebSecurity
|
||||||
|
public class WebSecurityConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
SecurityFilterChain securityFilterChain(HttpSecurity http) {
|
||||||
|
http.headers((headers) -> headers
|
||||||
|
.crossOriginOpenerPolicy(CrossOriginOpenerPolicy.SAME_ORIGIN)
|
||||||
|
.crossOriginEmbedderPolicy(CrossOriginEmbedderPolicy.REQUIRE_CORP)
|
||||||
|
.crossOriginResourcePolicy(CrossOriginResourcePolicy.SAME_ORIGIN)));
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
----
|
||||||
|
.Kotlin
|
||||||
|
[source,kotlin,role="secondary"]
|
||||||
|
----
|
||||||
|
@EnableWebSecurity
|
||||||
|
open class CrossOriginPoliciesConfig {
|
||||||
|
@Bean
|
||||||
|
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||||
|
http {
|
||||||
|
headers {
|
||||||
|
crossOriginOpenerPolicy(CrossOriginOpenerPolicy.SAME_ORIGIN)
|
||||||
|
crossOriginEmbedderPolicy(CrossOriginEmbedderPolicy.REQUIRE_CORP)
|
||||||
|
crossOriginResourcePolicy(CrossOriginResourcePolicy.SAME_ORIGIN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return http.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
This configuration will write the headers with the values provided:
|
||||||
|
[source]
|
||||||
|
----
|
||||||
|
Cross-Origin-Opener-Policy: same-origin
|
||||||
|
Cross-Origin-Embedder-Policy: require-corp
|
||||||
|
Cross-Origin-Resource-Policy: same-origin
|
||||||
|
----
|
||||||
|
|
||||||
[[servlet-headers-custom]]
|
[[servlet-headers-custom]]
|
||||||
== Custom Headers
|
== Custom Headers
|
||||||
Spring Security has mechanisms to make it convenient to add the more common security headers to your application.
|
Spring Security has mechanisms to make it convenient to add the more common security headers to your application.
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts Cross-Origin-Embedder-Policy header.
|
||||||
|
*
|
||||||
|
* @author Marcus Da Coregio
|
||||||
|
* @since 5.7
|
||||||
|
* @see <a href=
|
||||||
|
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy">
|
||||||
|
* Cross-Origin-Embedder-Policy</a>
|
||||||
|
*/
|
||||||
|
public final class CrossOriginEmbedderPolicyHeaderWriter implements HeaderWriter {
|
||||||
|
|
||||||
|
private static final String EMBEDDER_POLICY = "Cross-Origin-Embedder-Policy";
|
||||||
|
|
||||||
|
private CrossOriginEmbedderPolicy policy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link CrossOriginEmbedderPolicy} value to be used in the
|
||||||
|
* {@code Cross-Origin-Embedder-Policy} header
|
||||||
|
* @param embedderPolicy the {@link CrossOriginEmbedderPolicy} to use
|
||||||
|
*/
|
||||||
|
public void setPolicy(CrossOriginEmbedderPolicy embedderPolicy) {
|
||||||
|
Assert.notNull(embedderPolicy, "embedderPolicy cannot be null");
|
||||||
|
this.policy = embedderPolicy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeHeaders(HttpServletRequest request, HttpServletResponse response) {
|
||||||
|
if (this.policy != null && !response.containsHeader(EMBEDDER_POLICY)) {
|
||||||
|
response.addHeader(EMBEDDER_POLICY, this.policy.getPolicy());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum CrossOriginEmbedderPolicy {
|
||||||
|
|
||||||
|
UNSAFE_NONE("unsafe-none"),
|
||||||
|
|
||||||
|
REQUIRE_CORP("require-corp");
|
||||||
|
|
||||||
|
private final String policy;
|
||||||
|
|
||||||
|
CrossOriginEmbedderPolicy(String policy) {
|
||||||
|
this.policy = policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPolicy() {
|
||||||
|
return this.policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CrossOriginEmbedderPolicy from(String embedderPolicy) {
|
||||||
|
for (CrossOriginEmbedderPolicy policy : values()) {
|
||||||
|
if (policy.getPolicy().equals(embedderPolicy)) {
|
||||||
|
return policy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts the Cross-Origin-Opener-Policy header
|
||||||
|
*
|
||||||
|
* @author Marcus Da Coregio
|
||||||
|
* @since 5.7
|
||||||
|
* @see <a href=
|
||||||
|
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy">
|
||||||
|
* Cross-Origin-Opener-Policy</a>
|
||||||
|
*/
|
||||||
|
public final class CrossOriginOpenerPolicyHeaderWriter implements HeaderWriter {
|
||||||
|
|
||||||
|
private static final String OPENER_POLICY = "Cross-Origin-Opener-Policy";
|
||||||
|
|
||||||
|
private CrossOriginOpenerPolicy policy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link CrossOriginOpenerPolicy} value to be used in the
|
||||||
|
* {@code Cross-Origin-Opener-Policy} header
|
||||||
|
* @param openerPolicy the {@link CrossOriginOpenerPolicy} to use
|
||||||
|
*/
|
||||||
|
public void setPolicy(CrossOriginOpenerPolicy openerPolicy) {
|
||||||
|
Assert.notNull(openerPolicy, "openerPolicy cannot be null");
|
||||||
|
this.policy = openerPolicy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeHeaders(HttpServletRequest request, HttpServletResponse response) {
|
||||||
|
if (this.policy != null && !response.containsHeader(OPENER_POLICY)) {
|
||||||
|
response.addHeader(OPENER_POLICY, this.policy.getPolicy());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum CrossOriginOpenerPolicy {
|
||||||
|
|
||||||
|
UNSAFE_NONE("unsafe-none"),
|
||||||
|
|
||||||
|
SAME_ORIGIN_ALLOW_POPUPS("same-origin-allow-popups"),
|
||||||
|
|
||||||
|
SAME_ORIGIN("same-origin");
|
||||||
|
|
||||||
|
private final String policy;
|
||||||
|
|
||||||
|
CrossOriginOpenerPolicy(String policy) {
|
||||||
|
this.policy = policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPolicy() {
|
||||||
|
return this.policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CrossOriginOpenerPolicy from(String openerPolicy) {
|
||||||
|
for (CrossOriginOpenerPolicy policy : values()) {
|
||||||
|
if (policy.getPolicy().equals(openerPolicy)) {
|
||||||
|
return policy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts Cross-Origin-Resource-Policy header
|
||||||
|
*
|
||||||
|
* @author Marcus Da Coregio
|
||||||
|
* @since 5.7
|
||||||
|
* @see <a href=
|
||||||
|
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy">
|
||||||
|
* Cross-Origin-Resource-Policy</a>
|
||||||
|
*/
|
||||||
|
public final class CrossOriginResourcePolicyHeaderWriter implements HeaderWriter {
|
||||||
|
|
||||||
|
private static final String RESOURCE_POLICY = "Cross-Origin-Resource-Policy";
|
||||||
|
|
||||||
|
private CrossOriginResourcePolicy policy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link CrossOriginResourcePolicy} value to be used in the
|
||||||
|
* {@code Cross-Origin-Resource-Policy} header
|
||||||
|
* @param resourcePolicy the {@link CrossOriginResourcePolicy} to use
|
||||||
|
*/
|
||||||
|
public void setPolicy(CrossOriginResourcePolicy resourcePolicy) {
|
||||||
|
Assert.notNull(resourcePolicy, "resourcePolicy cannot be null");
|
||||||
|
this.policy = resourcePolicy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeHeaders(HttpServletRequest request, HttpServletResponse response) {
|
||||||
|
if (this.policy != null && !response.containsHeader(RESOURCE_POLICY)) {
|
||||||
|
response.addHeader(RESOURCE_POLICY, this.policy.getPolicy());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum CrossOriginResourcePolicy {
|
||||||
|
|
||||||
|
SAME_SITE("same-site"),
|
||||||
|
|
||||||
|
SAME_ORIGIN("same-origin"),
|
||||||
|
|
||||||
|
CROSS_ORIGIN("cross-origin");
|
||||||
|
|
||||||
|
private final String policy;
|
||||||
|
|
||||||
|
CrossOriginResourcePolicy(String policy) {
|
||||||
|
this.policy = policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPolicy() {
|
||||||
|
return this.policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CrossOriginResourcePolicy from(String resourcePolicy) {
|
||||||
|
for (CrossOriginResourcePolicy policy : values()) {
|
||||||
|
if (policy.getPolicy().equals(resourcePolicy)) {
|
||||||
|
return policy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://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.server.header;
|
||||||
|
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts Cross-Origin-Embedder-Policy headers.
|
||||||
|
*
|
||||||
|
* @author Marcus Da Coregio
|
||||||
|
* @since 5.7
|
||||||
|
* @see <a href=
|
||||||
|
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy">
|
||||||
|
* Cross-Origin-Embedder-Policy</a>
|
||||||
|
*/
|
||||||
|
public final class CrossOriginEmbedderPolicyServerHttpHeadersWriter implements ServerHttpHeadersWriter {
|
||||||
|
|
||||||
|
public static final String EMBEDDER_POLICY = "Cross-Origin-Embedder-Policy";
|
||||||
|
|
||||||
|
private ServerHttpHeadersWriter delegate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link CrossOriginEmbedderPolicy} value to be used in the
|
||||||
|
* {@code Cross-Origin-Embedder-Policy} header
|
||||||
|
* @param embedderPolicy the {@link CrossOriginEmbedderPolicy} to use
|
||||||
|
*/
|
||||||
|
public void setPolicy(CrossOriginEmbedderPolicy embedderPolicy) {
|
||||||
|
Assert.notNull(embedderPolicy, "embedderPolicy cannot be null");
|
||||||
|
this.delegate = createDelegate(embedderPolicy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<Void> writeHttpHeaders(ServerWebExchange exchange) {
|
||||||
|
return (this.delegate != null) ? this.delegate.writeHttpHeaders(exchange) : Mono.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ServerHttpHeadersWriter createDelegate(CrossOriginEmbedderPolicy embedderPolicy) {
|
||||||
|
StaticServerHttpHeadersWriter.Builder builder = StaticServerHttpHeadersWriter.builder();
|
||||||
|
builder.header(EMBEDDER_POLICY, embedderPolicy.getPolicy());
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum CrossOriginEmbedderPolicy {
|
||||||
|
|
||||||
|
UNSAFE_NONE("unsafe-none"),
|
||||||
|
|
||||||
|
REQUIRE_CORP("require-corp");
|
||||||
|
|
||||||
|
private final String policy;
|
||||||
|
|
||||||
|
CrossOriginEmbedderPolicy(String policy) {
|
||||||
|
this.policy = policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPolicy() {
|
||||||
|
return this.policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://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.server.header;
|
||||||
|
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts Cross-Origin-Opener-Policy header.
|
||||||
|
*
|
||||||
|
* @author Marcus Da Coregio
|
||||||
|
* @since 5.7
|
||||||
|
* @see <a href=
|
||||||
|
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy">
|
||||||
|
* Cross-Origin-Opener-Policy</a>
|
||||||
|
*/
|
||||||
|
public final class CrossOriginOpenerPolicyServerHttpHeadersWriter implements ServerHttpHeadersWriter {
|
||||||
|
|
||||||
|
public static final String OPENER_POLICY = "Cross-Origin-Opener-Policy";
|
||||||
|
|
||||||
|
private ServerHttpHeadersWriter delegate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link CrossOriginOpenerPolicy} value to be used in the
|
||||||
|
* {@code Cross-Origin-Opener-Policy} header
|
||||||
|
* @param openerPolicy the {@link CrossOriginOpenerPolicy} to use
|
||||||
|
*/
|
||||||
|
public void setPolicy(CrossOriginOpenerPolicy openerPolicy) {
|
||||||
|
Assert.notNull(openerPolicy, "openerPolicy cannot be null");
|
||||||
|
this.delegate = createDelegate(openerPolicy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<Void> writeHttpHeaders(ServerWebExchange exchange) {
|
||||||
|
return (this.delegate != null) ? this.delegate.writeHttpHeaders(exchange) : Mono.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ServerHttpHeadersWriter createDelegate(CrossOriginOpenerPolicy openerPolicy) {
|
||||||
|
StaticServerHttpHeadersWriter.Builder builder = StaticServerHttpHeadersWriter.builder();
|
||||||
|
builder.header(OPENER_POLICY, openerPolicy.getPolicy());
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum CrossOriginOpenerPolicy {
|
||||||
|
|
||||||
|
UNSAFE_NONE("unsafe-none"),
|
||||||
|
|
||||||
|
SAME_ORIGIN_ALLOW_POPUPS("same-origin-allow-popups"),
|
||||||
|
|
||||||
|
SAME_ORIGIN("same-origin");
|
||||||
|
|
||||||
|
private final String policy;
|
||||||
|
|
||||||
|
CrossOriginOpenerPolicy(String policy) {
|
||||||
|
this.policy = policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPolicy() {
|
||||||
|
return this.policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://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.server.header;
|
||||||
|
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts Cross-Origin-Resource-Policy headers.
|
||||||
|
*
|
||||||
|
* @author Marcus Da Coregio
|
||||||
|
* @since 5.7
|
||||||
|
* @see <a href=
|
||||||
|
* "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy">
|
||||||
|
* Cross-Origin-Resource-Policy</a>
|
||||||
|
*/
|
||||||
|
public final class CrossOriginResourcePolicyServerHttpHeadersWriter implements ServerHttpHeadersWriter {
|
||||||
|
|
||||||
|
public static final String RESOURCE_POLICY = "Cross-Origin-Resource-Policy";
|
||||||
|
|
||||||
|
private ServerHttpHeadersWriter delegate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link CrossOriginResourcePolicy} value to be used in the
|
||||||
|
* {@code Cross-Origin-Embedder-Policy} header
|
||||||
|
* @param resourcePolicy the {@link CrossOriginResourcePolicy} to use
|
||||||
|
*/
|
||||||
|
public void setPolicy(CrossOriginResourcePolicy resourcePolicy) {
|
||||||
|
Assert.notNull(resourcePolicy, "resourcePolicy cannot be null");
|
||||||
|
this.delegate = createDelegate(resourcePolicy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<Void> writeHttpHeaders(ServerWebExchange exchange) {
|
||||||
|
return (this.delegate != null) ? this.delegate.writeHttpHeaders(exchange) : Mono.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ServerHttpHeadersWriter createDelegate(CrossOriginResourcePolicy resourcePolicy) {
|
||||||
|
StaticServerHttpHeadersWriter.Builder builder = StaticServerHttpHeadersWriter.builder();
|
||||||
|
builder.header(RESOURCE_POLICY, resourcePolicy.getPolicy());
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum CrossOriginResourcePolicy {
|
||||||
|
|
||||||
|
SAME_SITE("same-site"),
|
||||||
|
|
||||||
|
SAME_ORIGIN("same-origin"),
|
||||||
|
|
||||||
|
CROSS_ORIGIN("cross-origin");
|
||||||
|
|
||||||
|
private final String policy;
|
||||||
|
|
||||||
|
CrossOriginResourcePolicy(String policy) {
|
||||||
|
this.policy = policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPolicy() {
|
||||||
|
return this.policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://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.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.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.assertThatIllegalArgumentException;
|
||||||
|
|
||||||
|
class CrossOriginEmbedderPolicyHeaderWriterTests {
|
||||||
|
|
||||||
|
private static final String EMBEDDER_HEADER_NAME = "Cross-Origin-Embedder-Policy";
|
||||||
|
|
||||||
|
private CrossOriginEmbedderPolicyHeaderWriter writer;
|
||||||
|
|
||||||
|
private MockHttpServletRequest request;
|
||||||
|
|
||||||
|
private MockHttpServletResponse response;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
this.writer = new CrossOriginEmbedderPolicyHeaderWriter();
|
||||||
|
this.request = new MockHttpServletRequest();
|
||||||
|
this.response = new MockHttpServletResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void setEmbedderPolicyWhenNullEmbedderPolicyThenThrowsIllegalArgument() {
|
||||||
|
assertThatIllegalArgumentException().isThrownBy(() -> this.writer.setPolicy(null))
|
||||||
|
.withMessage("embedderPolicy cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenDefaultValuesThenDontWriteHeaders() {
|
||||||
|
this.writer.writeHeaders(this.request, this.response);
|
||||||
|
assertThat(this.response.getHeaderNames()).hasSize(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenResponseHeaderExistsThenDontOverride() {
|
||||||
|
this.response.addHeader(EMBEDDER_HEADER_NAME, "require-corp");
|
||||||
|
this.writer.setPolicy(CrossOriginEmbedderPolicyHeaderWriter.CrossOriginEmbedderPolicy.UNSAFE_NONE);
|
||||||
|
this.writer.writeHeaders(this.request, this.response);
|
||||||
|
assertThat(this.response.getHeader(EMBEDDER_HEADER_NAME)).isEqualTo("require-corp");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenSetHeaderValuesThenWrites() {
|
||||||
|
this.writer.setPolicy(CrossOriginEmbedderPolicyHeaderWriter.CrossOriginEmbedderPolicy.REQUIRE_CORP);
|
||||||
|
this.writer.writeHeaders(this.request, this.response);
|
||||||
|
assertThat(this.response.getHeader(EMBEDDER_HEADER_NAME)).isEqualTo("require-corp");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenSetEmbedderPolicyThenWritesEmbedderPolicy() {
|
||||||
|
this.writer.setPolicy(CrossOriginEmbedderPolicyHeaderWriter.CrossOriginEmbedderPolicy.UNSAFE_NONE);
|
||||||
|
this.writer.writeHeaders(this.request, this.response);
|
||||||
|
assertThat(this.response.getHeaderNames()).hasSize(1);
|
||||||
|
assertThat(this.response.getHeader(EMBEDDER_HEADER_NAME)).isEqualTo("unsafe-none");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://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.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.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.assertThatIllegalArgumentException;
|
||||||
|
|
||||||
|
class CrossOriginOpenerPolicyHeaderWriterTests {
|
||||||
|
|
||||||
|
private static final String OPENER_HEADER_NAME = "Cross-Origin-Opener-Policy";
|
||||||
|
|
||||||
|
private CrossOriginOpenerPolicyHeaderWriter writer;
|
||||||
|
|
||||||
|
private MockHttpServletRequest request;
|
||||||
|
|
||||||
|
private MockHttpServletResponse response;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
this.writer = new CrossOriginOpenerPolicyHeaderWriter();
|
||||||
|
this.request = new MockHttpServletRequest();
|
||||||
|
this.response = new MockHttpServletResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void setOpenerPolicyWhenNullOpenerPolicyThenThrowsIllegalArgument() {
|
||||||
|
assertThatIllegalArgumentException().isThrownBy(() -> this.writer.setPolicy(null))
|
||||||
|
.withMessage("openerPolicy cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenDefaultValuesThenDontWriteHeaders() {
|
||||||
|
this.writer.writeHeaders(this.request, this.response);
|
||||||
|
assertThat(this.response.getHeaderNames()).hasSize(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenResponseHeaderExistsThenDontOverride() {
|
||||||
|
this.response.addHeader(OPENER_HEADER_NAME, "same-origin");
|
||||||
|
this.writer.setPolicy(CrossOriginOpenerPolicyHeaderWriter.CrossOriginOpenerPolicy.SAME_ORIGIN_ALLOW_POPUPS);
|
||||||
|
this.writer.writeHeaders(this.request, this.response);
|
||||||
|
assertThat(this.response.getHeader(OPENER_HEADER_NAME)).isEqualTo("same-origin");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenSetHeaderValuesThenWrites() {
|
||||||
|
this.writer.setPolicy(CrossOriginOpenerPolicyHeaderWriter.CrossOriginOpenerPolicy.SAME_ORIGIN_ALLOW_POPUPS);
|
||||||
|
this.writer.writeHeaders(this.request, this.response);
|
||||||
|
assertThat(this.response.getHeader(OPENER_HEADER_NAME)).isEqualTo("same-origin-allow-popups");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenSetOpenerPolicyThenWritesOpenerPolicy() {
|
||||||
|
this.writer.setPolicy(CrossOriginOpenerPolicyHeaderWriter.CrossOriginOpenerPolicy.SAME_ORIGIN_ALLOW_POPUPS);
|
||||||
|
this.writer.writeHeaders(this.request, this.response);
|
||||||
|
assertThat(this.response.getHeaderNames()).hasSize(1);
|
||||||
|
assertThat(this.response.getHeader(OPENER_HEADER_NAME)).isEqualTo("same-origin-allow-popups");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://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.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.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.assertThatIllegalArgumentException;
|
||||||
|
|
||||||
|
class CrossOriginResourcePolicyHeaderWriterTests {
|
||||||
|
|
||||||
|
private static final String RESOURCE_HEADER_NAME = "Cross-Origin-Resource-Policy";
|
||||||
|
|
||||||
|
private CrossOriginResourcePolicyHeaderWriter writer;
|
||||||
|
|
||||||
|
private MockHttpServletRequest request;
|
||||||
|
|
||||||
|
private MockHttpServletResponse response;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
this.writer = new CrossOriginResourcePolicyHeaderWriter();
|
||||||
|
this.request = new MockHttpServletRequest();
|
||||||
|
this.response = new MockHttpServletResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void setResourcePolicyWhenNullThenThrowsIllegalArgument() {
|
||||||
|
assertThatIllegalArgumentException().isThrownBy(() -> this.writer.setPolicy(null))
|
||||||
|
.withMessage("resourcePolicy cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenDefaultValuesThenDontWriteHeaders() {
|
||||||
|
this.writer.writeHeaders(this.request, this.response);
|
||||||
|
assertThat(this.response.getHeaderNames()).hasSize(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenResponseHeaderExistsThenDontOverride() {
|
||||||
|
this.response.addHeader(RESOURCE_HEADER_NAME, "same-site");
|
||||||
|
this.writer.setPolicy(CrossOriginResourcePolicyHeaderWriter.CrossOriginResourcePolicy.CROSS_ORIGIN);
|
||||||
|
this.writer.writeHeaders(this.request, this.response);
|
||||||
|
assertThat(this.response.getHeader(RESOURCE_HEADER_NAME)).isEqualTo("same-site");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenSetHeaderValuesThenWrites() {
|
||||||
|
this.writer.setPolicy(CrossOriginResourcePolicyHeaderWriter.CrossOriginResourcePolicy.SAME_ORIGIN);
|
||||||
|
this.writer.writeHeaders(this.request, this.response);
|
||||||
|
assertThat(this.response.getHeader(RESOURCE_HEADER_NAME)).isEqualTo("same-origin");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenSetResourcePolicyThenWritesResourcePolicy() {
|
||||||
|
this.writer.setPolicy(CrossOriginResourcePolicyHeaderWriter.CrossOriginResourcePolicy.SAME_SITE);
|
||||||
|
this.writer.writeHeaders(this.request, this.response);
|
||||||
|
assertThat(this.response.getHeaderNames()).hasSize(1);
|
||||||
|
assertThat(this.response.getHeader(RESOURCE_HEADER_NAME)).isEqualTo("same-site");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://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.server.header;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
|
||||||
|
import org.springframework.mock.web.server.MockServerWebExchange;
|
||||||
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||||
|
|
||||||
|
class CrossOriginEmbedderPolicyServerHttpHeadersWriterTests {
|
||||||
|
|
||||||
|
private ServerWebExchange exchange;
|
||||||
|
|
||||||
|
private CrossOriginEmbedderPolicyServerHttpHeadersWriter writer;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
this.exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/"));
|
||||||
|
this.writer = new CrossOriginEmbedderPolicyServerHttpHeadersWriter();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void setEmbedderPolicyWhenNullEmbedderPolicyThenThrowsIllegalArgument() {
|
||||||
|
assertThatIllegalArgumentException().isThrownBy(() -> this.writer.setPolicy(null))
|
||||||
|
.withMessage("embedderPolicy cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenNoValuesThenDoesNotWriteHeaders() {
|
||||||
|
this.writer.writeHttpHeaders(this.exchange);
|
||||||
|
HttpHeaders headers = this.exchange.getResponse().getHeaders();
|
||||||
|
assertThat(headers).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenResponseHeaderExistsThenDontOverride() {
|
||||||
|
this.exchange.getResponse().getHeaders().add(CrossOriginEmbedderPolicyServerHttpHeadersWriter.EMBEDDER_POLICY,
|
||||||
|
"require-corp");
|
||||||
|
this.writer.writeHttpHeaders(this.exchange);
|
||||||
|
HttpHeaders headers = this.exchange.getResponse().getHeaders();
|
||||||
|
assertThat(headers).hasSize(1);
|
||||||
|
assertThat(headers.get(CrossOriginEmbedderPolicyServerHttpHeadersWriter.EMBEDDER_POLICY))
|
||||||
|
.containsOnly("require-corp");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenSetHeaderValuesThenWrites() {
|
||||||
|
this.writer.setPolicy(CrossOriginEmbedderPolicyServerHttpHeadersWriter.CrossOriginEmbedderPolicy.REQUIRE_CORP);
|
||||||
|
this.writer.writeHttpHeaders(this.exchange);
|
||||||
|
HttpHeaders headers = this.exchange.getResponse().getHeaders();
|
||||||
|
assertThat(headers).hasSize(1);
|
||||||
|
assertThat(headers.get(CrossOriginEmbedderPolicyServerHttpHeadersWriter.EMBEDDER_POLICY))
|
||||||
|
.containsOnly("require-corp");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://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.server.header;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
|
||||||
|
import org.springframework.mock.web.server.MockServerWebExchange;
|
||||||
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||||
|
|
||||||
|
class CrossOriginOpenerPolicyServerHttpHeadersWriterTests {
|
||||||
|
|
||||||
|
private ServerWebExchange exchange;
|
||||||
|
|
||||||
|
private CrossOriginOpenerPolicyServerHttpHeadersWriter writer;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
this.exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/"));
|
||||||
|
this.writer = new CrossOriginOpenerPolicyServerHttpHeadersWriter();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void setOpenerPolicyWhenNullOpenerPolicyThenThrowsIllegalArgument() {
|
||||||
|
assertThatIllegalArgumentException().isThrownBy(() -> this.writer.setPolicy(null))
|
||||||
|
.withMessage("openerPolicy cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenNoValuesThenDoesNotWriteHeaders() {
|
||||||
|
this.writer.writeHttpHeaders(this.exchange);
|
||||||
|
HttpHeaders headers = this.exchange.getResponse().getHeaders();
|
||||||
|
assertThat(headers).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenResponseHeaderExistsThenDontOverride() {
|
||||||
|
this.exchange.getResponse().getHeaders().add(CrossOriginOpenerPolicyServerHttpHeadersWriter.OPENER_POLICY,
|
||||||
|
"same-origin");
|
||||||
|
this.writer.writeHttpHeaders(this.exchange);
|
||||||
|
HttpHeaders headers = this.exchange.getResponse().getHeaders();
|
||||||
|
assertThat(headers).hasSize(1);
|
||||||
|
assertThat(headers.get(CrossOriginOpenerPolicyServerHttpHeadersWriter.OPENER_POLICY))
|
||||||
|
.containsOnly("same-origin");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenSetHeaderValuesThenWrites() {
|
||||||
|
this.writer.setPolicy(
|
||||||
|
CrossOriginOpenerPolicyServerHttpHeadersWriter.CrossOriginOpenerPolicy.SAME_ORIGIN_ALLOW_POPUPS);
|
||||||
|
this.writer.writeHttpHeaders(this.exchange);
|
||||||
|
HttpHeaders headers = this.exchange.getResponse().getHeaders();
|
||||||
|
assertThat(headers).hasSize(1);
|
||||||
|
assertThat(headers.get(CrossOriginOpenerPolicyServerHttpHeadersWriter.OPENER_POLICY))
|
||||||
|
.containsOnly("same-origin-allow-popups");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://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.server.header;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
|
||||||
|
import org.springframework.mock.web.server.MockServerWebExchange;
|
||||||
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||||
|
|
||||||
|
class CrossOriginResourcePolicyServerHttpHeadersWriterTests {
|
||||||
|
|
||||||
|
private ServerWebExchange exchange;
|
||||||
|
|
||||||
|
private CrossOriginResourcePolicyServerHttpHeadersWriter writer;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
this.exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/"));
|
||||||
|
this.writer = new CrossOriginResourcePolicyServerHttpHeadersWriter();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void setResourcePolicyWhenNullThenThrowsIllegalArgument() {
|
||||||
|
assertThatIllegalArgumentException().isThrownBy(() -> this.writer.setPolicy(null))
|
||||||
|
.withMessage("resourcePolicy cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenNoValuesThenDoesNotWriteHeaders() {
|
||||||
|
this.writer.writeHttpHeaders(this.exchange);
|
||||||
|
HttpHeaders headers = this.exchange.getResponse().getHeaders();
|
||||||
|
assertThat(headers).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenResponseHeaderExistsThenDontOverride() {
|
||||||
|
this.exchange.getResponse().getHeaders().add(CrossOriginResourcePolicyServerHttpHeadersWriter.RESOURCE_POLICY,
|
||||||
|
"same-origin");
|
||||||
|
this.writer.writeHttpHeaders(this.exchange);
|
||||||
|
HttpHeaders headers = this.exchange.getResponse().getHeaders();
|
||||||
|
assertThat(headers).hasSize(1);
|
||||||
|
assertThat(headers.get(CrossOriginResourcePolicyServerHttpHeadersWriter.RESOURCE_POLICY))
|
||||||
|
.containsOnly("same-origin");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeHeadersWhenSetHeaderValuesThenWrites() {
|
||||||
|
this.writer.setPolicy(CrossOriginResourcePolicyServerHttpHeadersWriter.CrossOriginResourcePolicy.SAME_ORIGIN);
|
||||||
|
this.writer.writeHttpHeaders(this.exchange);
|
||||||
|
HttpHeaders headers = this.exchange.getResponse().getHeaders();
|
||||||
|
assertThat(headers).hasSize(1);
|
||||||
|
assertThat(headers.get(CrossOriginResourcePolicyServerHttpHeadersWriter.RESOURCE_POLICY))
|
||||||
|
.containsOnly("same-origin");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue