Skip to content

Commit 3617fd2

Browse files
rhamedyjzheaux
authored andcommitted
Introduced placeholder support for Headers tag attributes
Added the functionality to allow the disabled and defaults-disabled attribute of <header> tag to accept a placeholder and resolve it during parsing. - Updated the spring-security .rnc files starting from 4.2 up to 5.2 with xsd:token type instead of boolean - Added unit tests for headers.disabled and headers.defaults-disabled attributes with placeholder - Modified the HeadersBeanDefinitionParser to support resolving placeholders - Updated spring.schemas to point to latest spring-security-5.2.xsd Fixes gh-6547
1 parent bfe1e6a commit 3617fd2

File tree

7 files changed

+176
-9
lines changed

7 files changed

+176
-9
lines changed

config/src/main/java/org/springframework/security/config/http/HeadersBeanDefinitionParser.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -49,6 +49,7 @@
4949
* @author Tim Ysewyn
5050
* @author Eddú Meléndez
5151
* @author Vedran Pavic
52+
* @author Rafiullah Hamedy
5253
* @since 3.2
5354
*/
5455
public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
@@ -95,14 +96,15 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
9596
private ManagedList<BeanMetadataElement> headerWriters;
9697

9798
public BeanDefinition parse(Element element, ParserContext parserContext) {
99+
98100
headerWriters = new ManagedList<>();
99101
BeanDefinitionBuilder builder = BeanDefinitionBuilder
100102
.rootBeanDefinition(HeaderWriterFilter.class);
101103

102104
boolean disabled = element != null
103-
&& "true".equals(element.getAttribute("disabled"));
105+
&& "true".equals(resolveAttribute(parserContext, element, "disabled"));
104106
boolean defaultsDisabled = element != null
105-
&& "true".equals(element.getAttribute("defaults-disabled"));
107+
&& "true".equals(resolveAttribute(parserContext, element, "defaults-disabled"));
106108

107109
boolean addIfNotPresent = element == null || !disabled && !defaultsDisabled;
108110

@@ -136,6 +138,19 @@ public BeanDefinition parse(Element element, ParserContext parserContext) {
136138
return builder.getBeanDefinition();
137139
}
138140

141+
/**
142+
*
143+
* Resolve the placeholder for a given attribute on a element.
144+
*
145+
* @param pc
146+
* @param element
147+
* @param attributeName
148+
* @return Resolved value of the placeholder
149+
*/
150+
private String resolveAttribute(ParserContext pc, Element element, String attributeName) {
151+
return pc.getReaderContext().getEnvironment().resolvePlaceholders(element.getAttribute(attributeName));
152+
}
153+
139154
private void parseCacheControlElement(boolean addIfNotPresent, Element element) {
140155
Element cacheControlElement = element == null ? null : DomUtils
141156
.getChildElementByTagName(element, CACHE_CONTROL_ELEMENT);

config/src/main/resources/META-INF/spring.schemas

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-5.1.xsd
1+
http\://www.springframework.org/schema/security/spring-security.xsd=org/springframework/security/config/spring-security-5.2.xsd
2+
http\://www.springframework.org/schema/security/spring-security-5.2.xsd=org/springframework/security/config/spring-security-5.2.xsd
23
http\://www.springframework.org/schema/security/spring-security-5.1.xsd=org/springframework/security/config/spring-security-5.1.xsd
34
http\://www.springframework.org/schema/security/spring-security-5.0.xsd=org/springframework/security/config/spring-security-5.0.xsd
45
http\://www.springframework.org/schema/security/spring-security-4.2.xsd=org/springframework/security/config/spring-security-4.2.xsd

config/src/main/resources/org/springframework/security/config/spring-security-5.2.rnc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -746,10 +746,10 @@ headers =
746746
element headers { headers-options.attlist, (cache-control? & xss-protection? & hsts? & frame-options? & content-type-options? & hpkp? & content-security-policy? & referrer-policy? & feature-policy? & header*)}
747747
headers-options.attlist &=
748748
## Specifies if the default headers should be disabled. Default false.
749-
attribute defaults-disabled {xsd:boolean}?
749+
attribute defaults-disabled {xsd:token}?
750750
headers-options.attlist &=
751751
## Specifies if headers should be disabled. Default false.
752-
attribute disabled {xsd:boolean}?
752+
attribute disabled {xsd:token}?
753753
hsts =
754754
## Adds support for HTTP Strict Transport Security (HSTS)
755755
element hsts {hsts-options.attlist}

config/src/main/resources/org/springframework/security/config/spring-security-5.2.xsd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2261,13 +2261,13 @@
22612261
</xs:complexType>
22622262
</xs:element>
22632263
<xs:attributeGroup name="headers-options.attlist">
2264-
<xs:attribute name="defaults-disabled" type="xs:boolean">
2264+
<xs:attribute name="defaults-disabled" type="xs:token">
22652265
<xs:annotation>
22662266
<xs:documentation>Specifies if the default headers should be disabled. Default false.
22672267
</xs:documentation>
22682268
</xs:annotation>
22692269
</xs:attribute>
2270-
<xs:attribute name="disabled" type="xs:boolean">
2270+
<xs:attribute name="disabled" type="xs:token">
22712271
<xs:annotation>
22722272
<xs:documentation>Specifies if headers should be disabled. Default false.
22732273
</xs:documentation>

config/src/test/java/org/springframework/security/config/http/HttpHeadersConfigTests.java

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -45,6 +45,7 @@
4545
* @author Rob Winch
4646
* @author Tim Ysewyn
4747
* @author Josh Cummings
48+
* @author Rafiullah Hamedy
4849
*/
4950
public class HttpHeadersConfigTests {
5051

@@ -79,6 +80,45 @@ public void requestWhenHeadersDisabledThenResponseExcludesAllSecureHeaders()
7980
.andExpect(excludesDefaults());
8081
}
8182

83+
@Test
84+
public void requestWhenHeadersDisabledViaPlaceholderThenResponseExcludesAllSecureHeaders()
85+
throws Exception {
86+
87+
System.setProperty("security.headers.disabled", "true");
88+
89+
this.spring.configLocations(this.xml("DisabledWithPlaceholder")).autowire();
90+
91+
this.mvc.perform(get("/").secure(true))
92+
.andExpect(status().isOk())
93+
.andExpect(excludesDefaults());
94+
}
95+
96+
@Test
97+
public void requestWhenHeadersEnabledViaPlaceholderThenResponseIncludesAllSecureHeaders()
98+
throws Exception {
99+
100+
System.setProperty("security.headers.disabled", "false");
101+
102+
this.spring.configLocations(this.xml("DisabledWithPlaceholder")).autowire();
103+
104+
this.mvc.perform(get("/").secure(true))
105+
.andExpect(status().isOk())
106+
.andExpect(includesDefaults());
107+
}
108+
109+
@Test
110+
public void requestWhenHeadersDisabledRefMissingPlaceholderThenResponseIncludesAllSecureHeaders()
111+
throws Exception {
112+
113+
System.clearProperty("security.headers.disabled");
114+
115+
this.spring.configLocations(this.xml("DisabledWithPlaceholder")).autowire();
116+
117+
this.mvc.perform(get("/").secure(true))
118+
.andExpect(status().isOk())
119+
.andExpect(includesDefaults());
120+
}
121+
82122
@Test
83123
public void configureWhenHeadersDisabledHavingChildElementThenAutowireFails() {
84124
assertThatThrownBy(() ->
@@ -139,6 +179,45 @@ public void requestWhenDefaultsDisabledWithNoOverrideThenExcludesAllSecureHeader
139179
.andExpect(excludesDefaults());
140180
}
141181

182+
@Test
183+
public void requestWhenDefaultsDisabledWithPlaceholderTrueThenExcludesAllSecureHeaders()
184+
throws Exception {
185+
186+
System.setProperty("security.headers.defaults.disabled", "true");
187+
188+
this.spring.configLocations(this.xml("DefaultsDisabledWithPlaceholder")).autowire();
189+
190+
this.mvc.perform(get("/").secure(true))
191+
.andExpect(status().isOk())
192+
.andExpect(excludesDefaults());
193+
}
194+
195+
@Test
196+
public void requestWhenDefaultsDisabledWithPlaceholderFalseThenIncludeAllSecureHeaders()
197+
throws Exception {
198+
199+
System.setProperty("security.headers.defaults.disabled", "false");
200+
201+
this.spring.configLocations(this.xml("DefaultsDisabledWithPlaceholder")).autowire();
202+
203+
this.mvc.perform(get("/").secure(true))
204+
.andExpect(status().isOk())
205+
.andExpect(includesDefaults());
206+
}
207+
208+
@Test
209+
public void requestWhenDefaultsDisabledWithPlaceholderMissingThenIncludeAllSecureHeaders()
210+
throws Exception {
211+
212+
System.clearProperty("security.headers.defaults.disabled");
213+
214+
this.spring.configLocations(this.xml("DefaultsDisabledWithPlaceholder")).autowire();
215+
216+
this.mvc.perform(get("/").secure(true))
217+
.andExpect(status().isOk())
218+
.andExpect(includesDefaults());
219+
}
220+
142221
@Test
143222
public void requestWhenUsingContentTypeOptionsThenDefaultsToNoSniff()
144223
throws Exception {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
~ Copyright 2002-2019 the original author or authors.
4+
~
5+
~ Licensed under the Apache License, Version 2.0 (the "License");
6+
~ you may not use this file except in compliance with the License.
7+
~ You may obtain a copy of the License at
8+
~
9+
~ http://www.apache.org/licenses/LICENSE-2.0
10+
~
11+
~ Unless required by applicable law or agreed to in writing, software
12+
~ distributed under the License is distributed on an "AS IS" BASIS,
13+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
~ See the License for the specific language governing permissions and
15+
~ limitations under the License.
16+
-->
17+
18+
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
19+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20+
xmlns="http://www.springframework.org/schema/security"
21+
xsi:schemaLocation="
22+
http://www.springframework.org/schema/security
23+
http://www.springframework.org/schema/security/spring-security.xsd
24+
http://www.springframework.org/schema/beans
25+
http://www.springframework.org/schema/beans/spring-beans.xsd">
26+
27+
<http auto-config="true">
28+
<headers defaults-disabled="${security.headers.defaults.disabled}"/>
29+
</http>
30+
31+
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
32+
33+
<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>
34+
35+
<b:import resource="userservice.xml"/>
36+
</b:beans>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
~ Copyright 2002-2019 the original author or authors.
4+
~
5+
~ Licensed under the Apache License, Version 2.0 (the "License");
6+
~ you may not use this file except in compliance with the License.
7+
~ You may obtain a copy of the License at
8+
~
9+
~ http://www.apache.org/licenses/LICENSE-2.0
10+
~
11+
~ Unless required by applicable law or agreed to in writing, software
12+
~ distributed under the License is distributed on an "AS IS" BASIS,
13+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
~ See the License for the specific language governing permissions and
15+
~ limitations under the License.
16+
-->
17+
18+
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
19+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20+
xmlns="http://www.springframework.org/schema/security"
21+
xsi:schemaLocation="
22+
http://www.springframework.org/schema/security
23+
http://www.springframework.org/schema/security/spring-security.xsd
24+
http://www.springframework.org/schema/beans
25+
http://www.springframework.org/schema/beans/spring-beans.xsd">
26+
27+
<http auto-config="true">
28+
<headers disabled="${security.headers.disabled}" />
29+
</http>
30+
31+
<b:bean name="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
32+
33+
<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>
34+
35+
<b:import resource="userservice.xml"/>
36+
</b:beans>

0 commit comments

Comments
 (0)