2019-11-07 11:55:27 -05:00
[[servlet-headers]]
2019-10-28 17:00:51 -04:00
= Security HTTP Response Headers
2018-03-06 11:57:57 -05:00
2021-07-30 17:56:54 -04:00
xref:overview/features/exploits/headers.adoc#headers[Security HTTP Response Headers] can be used to increase the security of web applications.
2019-11-07 11:55:27 -05:00
This section is dedicated to servlet based support for Security HTTP Response Headers.
2018-03-06 11:57:57 -05:00
2019-11-07 11:55:27 -05:00
[[servlet-headers-default]]
== Default Security Headers
2018-03-06 11:57:57 -05:00
2021-07-30 17:56:54 -04:00
Spring Security provides a xref:overview/features/exploits/headers.adoc#headers-default[default set of Security HTTP Response Headers] to provide secure defaults.
2018-03-06 11:57:57 -05:00
While each of these headers are considered best practice, it should be noted that not all clients utilize the headers, so additional testing is encouraged.
You can customize specific headers.
2019-11-07 11:55:27 -05:00
For example, assume that you want the defaults except you wish to specify `SAMEORIGIN` for <<servlet-headers-frame-options,X-Frame-Options>>.
2018-03-06 11:57:57 -05:00
2020-07-10 10:08:02 -04:00
You can easily do this with the following Configuration:
2018-03-06 11:57:57 -05:00
2020-07-10 10:08:02 -04:00
.Customize Default Security Headers
2019-11-07 11:55:27 -05:00
====
2020-07-10 10:08:02 -04:00
.Java
[source,java,role="primary"]
2018-03-06 11:57:57 -05:00
----
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Override
2019-11-07 11:55:27 -05:00
protected void configure(HttpSecurity http) {
2018-03-06 11:57:57 -05:00
http
// ...
2020-01-10 07:10:36 -05:00
.headers(headers -> headers
.frameOptions(frameOptions -> frameOptions
.sameOrigin()
)
2019-07-12 13:58:17 -04:00
);
2018-03-06 11:57:57 -05:00
}
}
----
2020-07-10 10:08:02 -04:00
.XML
[source,xml,role="secondary"]
2018-03-06 11:57:57 -05:00
----
<http>
<!-- ... -->
<headers>
<frame-options policy="SAMEORIGIN" />
</headers>
</http>
----
2020-07-10 10:08:02 -04:00
.Kotlin
[source,kotlin,role="secondary"]
----
@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http {
// ...
headers {
frameOptions {
sameOrigin = true
}
}
}
}
}
----
2019-11-07 11:55:27 -05:00
====
2018-03-06 11:57:57 -05:00
If you do not want the defaults to be added and want explicit control over what should be used, you can disable the defaults.
2020-07-10 10:08:02 -04:00
An example is provided below:
2018-03-06 11:57:57 -05:00
2021-07-30 17:56:54 -04:00
If you are using Spring Security's Configuration the following will only add xref:overview/features/exploits/headers.adoc#headers-cache-control[Cache Control].
2018-03-06 11:57:57 -05:00
2020-07-10 10:08:02 -04:00
.Customize Cache Control Headers
====
.Java
[source,java,role="primary"]
2018-03-06 11:57:57 -05:00
----
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
2019-11-07 11:55:27 -05:00
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
2020-01-10 07:10:36 -05:00
.headers(headers -> headers
// do not use any default headers unless explicitly listed
.defaultsDisabled()
.cacheControl(withDefaults())
2019-11-07 11:55:27 -05:00
);
}
2018-03-06 11:57:57 -05:00
}
----
2020-07-10 10:08:02 -04:00
.XML
[source,xml,role="secondary"]
2018-03-06 11:57:57 -05:00
----
<http>
<!-- ... -->
<headers defaults-disabled="true">
<cache-control/>
</headers>
</http>
----
2020-07-10 10:08:02 -04:00
.Kotlin
[source,kotlin,role="secondary"]
----
@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http {
// ...
headers {
// do not use any default headers unless explicitly listed
defaultsDisabled = true
cacheControl {
}
}
}
}
}
----
====
2018-03-06 11:57:57 -05:00
2020-07-10 10:08:02 -04:00
If necessary, you can disable all of the HTTP Security response headers with the following Configuration:
2018-03-06 11:57:57 -05:00
2020-07-10 10:08:02 -04:00
.Disable All HTTP Security Headers
====
.Java
[source,java,role="primary"]
2018-03-06 11:57:57 -05:00
----
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
2019-11-07 11:55:27 -05:00
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
2020-01-10 07:10:36 -05:00
.headers(headers -> headers.disable());
2019-11-07 11:55:27 -05:00
}
2018-03-06 11:57:57 -05:00
}
----
2020-07-10 10:08:02 -04:00
.XML
[source,xml,role="secondary"]
2018-03-06 11:57:57 -05:00
----
<http>
<!-- ... -->
<headers disabled="true" />
</http>
----
2020-07-10 10:08:02 -04:00
.Kotlin
[source,kotlin,role="secondary"]
----
@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http {
// ...
headers {
disable()
}
}
}
}
----
====
2019-11-07 11:55:27 -05:00
[[servlet-headers-cache-control]]
2019-10-28 17:00:51 -04:00
== Cache Control
2018-03-06 11:57:57 -05:00
2021-07-30 17:56:54 -04:00
Spring Security includes xref:overview/features/exploits/headers.adoc#headers-cache-control[Cache Control] headers by default.
2018-03-06 11:57:57 -05:00
2019-11-07 11:55:27 -05:00
However, if you actually want to cache specific responses, your application can selectively invoke https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletResponse.html#setHeader(java.lang.String,java.lang.String)[HttpServletResponse.setHeader(String,String)] to override the header set by Spring Security.
This is useful to ensure things like CSS, JavaScript, and images are properly cached.
2018-03-06 11:57:57 -05:00
2019-11-07 11:55:27 -05:00
When using Spring Web MVC, this is typically done within your configuration.
Details on how to do this can be found in the https://docs.spring.io/spring/docs/5.0.0.RELEASE/spring-framework-reference/web.html#mvc-config-static-resources[Static Resources] portion of the Spring Reference documentation
2018-03-06 11:57:57 -05:00
2019-11-07 11:55:27 -05:00
If necessary, you can also disable Spring Security's cache control HTTP response headers.
2018-03-06 11:57:57 -05:00
2020-07-10 10:08:02 -04:00
.Cache Control Disabled
2019-11-07 11:55:27 -05:00
====
2020-07-10 10:08:02 -04:00
.Java
[source,java,role="primary"]
2018-03-06 11:57:57 -05:00
----
2019-11-07 11:55:27 -05:00
@Configuration
2018-03-06 11:57:57 -05:00
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
2019-11-07 11:55:27 -05:00
@Override
protected void configure(HttpSecurity http) {
http
// ...
2020-01-10 07:10:36 -05:00
.headers(headers -> headers
.cacheControl(cache -> cache.disable())
2019-11-07 11:55:27 -05:00
);
}
2018-03-06 11:57:57 -05:00
}
----
2020-07-10 10:08:02 -04:00
.XML
[source,xml,role="secondary"]
2018-03-06 11:57:57 -05:00
----
2019-11-07 11:55:27 -05:00
<http>
<!-- ... -->
2018-03-06 11:57:57 -05:00
2019-11-07 11:55:27 -05:00
<headers>
<cache-control disabled="true"/>
</headers>
</http>
2018-03-06 11:57:57 -05:00
----
2020-07-10 10:08:02 -04:00
.Kotlin
[source,kotlin,role="secondary"]
----
@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http {
headers {
cacheControl {
disable()
}
}
}
}
}
----
2019-11-07 11:55:27 -05:00
====
2018-03-06 11:57:57 -05:00
2019-11-07 11:55:27 -05:00
[[servlet-headers-content-type-options]]
2019-10-28 17:00:51 -04:00
== Content Type Options
2018-03-06 11:57:57 -05:00
2021-07-30 17:56:54 -04:00
Spring Security includes xref:overview/features/exploits/headers.adoc#headers-content-type-options[Content-Type] headers by default.
2020-07-10 10:08:02 -04:00
However, you can disable it with:
2018-03-06 11:57:57 -05:00
2020-07-10 10:08:02 -04:00
.Content Type Options Disabled
2019-11-07 11:55:27 -05:00
====
2020-07-10 10:08:02 -04:00
.Java
[source,java,role="primary"]
2018-03-06 11:57:57 -05:00
----
2019-11-07 11:55:27 -05:00
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) {
http
// ...
2020-01-10 07:10:36 -05:00
.headers(headers -> headers
.contentTypeOptions(contentTypeOptions -> contentTypeOptions.disable())
2019-11-07 11:55:27 -05:00
);
}
}
2018-03-06 11:57:57 -05:00
----
2020-07-10 10:08:02 -04:00
.XML
[source,xml,role="secondary"]
2018-03-06 11:57:57 -05:00
----
<http>
<!-- ... -->
2019-11-07 11:55:27 -05:00
<headers>
<content-type-options disabled="true"/>
2018-03-06 11:57:57 -05:00
</headers>
</http>
----
2020-07-10 10:08:02 -04:00
.Kotlin
[source,kotlin,role="secondary"]
----
@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http {
headers {
contentTypeOptions {
disable()
}
}
}
}
}
----
2019-11-07 11:55:27 -05:00
====
[[servlet-headers-hsts]]
== HTTP Strict Transport Security (HSTS)
2018-03-06 11:57:57 -05:00
2021-07-30 17:56:54 -04:00
Spring Security provides the xref:overview/features/exploits/headers.adoc#headers-hsts[Strict Transport Security] header by default.
2019-11-07 11:55:27 -05:00
However, you can customize the results explicitly.
2020-07-10 10:08:02 -04:00
For example, the following is an example of explicitly providing HSTS:
2018-03-06 11:57:57 -05:00
2020-07-10 10:08:02 -04:00
.Strict Transport Security
2019-11-07 11:55:27 -05:00
====
2020-07-10 10:08:02 -04:00
.Java
[source,java,role="primary"]
2018-03-06 11:57:57 -05:00
----
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
2019-11-07 11:55:27 -05:00
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
2020-01-10 07:10:36 -05:00
.headers(headers -> headers
.httpStrictTransportSecurity(hsts -> hsts
.includeSubDomains(true)
.preload(true)
.maxAgeInSeconds(31536000)
)
2019-11-07 11:55:27 -05:00
);
}
2018-03-06 11:57:57 -05:00
}
----
2018-12-21 11:29:54 -05:00
2020-07-10 10:08:02 -04:00
.XML
[source,xml,role="secondary"]
2018-03-06 11:57:57 -05:00
----
<http>
<!-- ... -->
<headers>
<hsts
include-subdomains="true"
2019-11-07 11:55:27 -05:00
max-age-seconds="31536000"
preload="true" />
2018-03-06 11:57:57 -05:00
</headers>
</http>
----
2020-07-10 10:08:02 -04:00
.Kotlin
[source,kotlin,role="secondary"]
----
@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http {
headers {
httpStrictTransportSecurity {
includeSubDomains = true
preload = true
maxAgeInSeconds = 31536000
}
}
}
}
}
----
2019-11-07 11:55:27 -05:00
====
[[servlet-headers-hpkp]]
== HTTP Public Key Pinning (HPKP)
2021-07-30 17:56:54 -04:00
For passivity reasons, Spring Security provides servlet support for xref:overview/features/exploits/headers.adoc#headers-hpkp[HTTP Public Key Pinning] but it is xref:overview/features/exploits/headers.adoc#headers-hpkp-deprecated[no longer recommended].
2018-03-06 11:57:57 -05:00
2020-07-10 10:08:02 -04:00
You can enable HPKP headers with the following Configuration:
2018-03-06 11:57:57 -05:00
2020-07-10 10:08:02 -04:00
.HTTP Public Key Pinning
2019-11-07 11:55:27 -05:00
====
2020-07-10 10:08:02 -04:00
.Java
[source,java,role="primary"]
2018-03-06 11:57:57 -05:00
----
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
2019-11-07 11:55:27 -05:00
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
2020-01-10 07:10:36 -05:00
.headers(headers -> headers
.httpPublicKeyPinning(hpkp -> hpkp
.includeSubDomains(true)
.reportUri("https://example.net/pkp-report")
.addSha256Pins("d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=", "E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=")
)
2019-11-07 11:55:27 -05:00
);
}
2018-03-06 11:57:57 -05:00
}
----
2020-07-10 10:08:02 -04:00
.XML
[source,xml,role="secondary"]
2018-03-06 11:57:57 -05:00
----
<http>
<!-- ... -->
<headers>
<hpkp
include-subdomains="true"
2019-03-20 00:53:23 -04:00
report-uri="https://example.net/pkp-report">
2018-03-06 11:57:57 -05:00
<pins>
2019-11-07 11:55:27 -05:00
<pin algorithm="sha256">d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=</pin>
<pin algorithm="sha256">E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=</pin>
2018-03-06 11:57:57 -05:00
</pins>
</hpkp>
</headers>
</http>
----
2019-11-07 11:55:27 -05:00
2020-07-10 10:08:02 -04:00
.Kotlin
[source,kotlin,role="secondary"]
----
@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http {
headers {
httpPublicKeyPinning {
includeSubDomains = true
reportUri = "https://example.net/pkp-report"
pins = mapOf("d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=" to "sha256",
"E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=" to "sha256")
}
}
}
}
}
----
====
2019-11-07 11:55:27 -05:00
[[servlet-headers-frame-options]]
== X-Frame-Options
2018-03-06 11:57:57 -05:00
2021-07-30 17:56:54 -04:00
By default, Spring Security disables rendering within an iframe using xref:overview/features/exploits/headers.adoc#headers-frame-options[X-Frame-Options].
2018-03-06 11:57:57 -05:00
2020-07-10 10:08:02 -04:00
You can customize frame options to use the same origin within a Configuration using the following:
2019-11-07 11:55:27 -05:00
2020-07-10 10:08:02 -04:00
.X-Frame-Options: SAMEORIGIN
2019-11-07 11:55:27 -05:00
====
2020-07-10 10:08:02 -04:00
.Java
[source,java,role="primary"]
2018-03-06 11:57:57 -05:00
----
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
2019-07-12 13:58:17 -04:00
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
2020-01-10 07:10:36 -05:00
.headers(headers -> headers
.frameOptions(frameOptions -> frameOptions
.sameOrigin()
)
2019-07-12 13:58:17 -04:00
);
}
2018-03-06 11:57:57 -05:00
}
----
2020-07-10 10:08:02 -04:00
.XML
[source,xml,role="secondary"]
2018-03-06 11:57:57 -05:00
----
<http>
<!-- ... -->
<headers>
<frame-options
policy="SAMEORIGIN" />
</headers>
</http>
----
2019-11-07 11:55:27 -05:00
2020-07-10 10:08:02 -04:00
.Kotlin
[source,kotlin,role="secondary"]
----
@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http {
headers {
frameOptions {
sameOrigin = true
}
}
}
}
}
----
====
2019-11-07 11:55:27 -05:00
[[servlet-headers-xss-protection]]
== X-XSS-Protection
2018-03-06 11:57:57 -05:00
2019-11-07 11:55:27 -05:00
By default, Spring Security instructs browsers to block reflected XSS attacks using the <<headers-xss-protection,X-XSS-Protection header>.
However, you can change this default.
2020-07-10 10:08:02 -04:00
For example, the following Configuration specifies that Spring Security should no longer instruct browsers to block the content:
2018-03-06 11:57:57 -05:00
2020-07-10 10:08:02 -04:00
.X-XSS-Protection Customization
2019-11-07 11:55:27 -05:00
====
2020-07-10 10:08:02 -04:00
.Java
[source,java,role="primary"]
2018-03-06 11:57:57 -05:00
----
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
2019-11-07 11:55:27 -05:00
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
2020-01-10 07:10:36 -05:00
.headers(headers -> headers
.xssProtection(xss -> xss
.block(false)
)
2019-11-07 11:55:27 -05:00
);
}
2018-03-06 11:57:57 -05:00
}
----
2020-07-10 10:08:02 -04:00
.XML
[source,xml,role="secondary"]
2018-03-06 11:57:57 -05:00
----
<http>
<!-- ... -->
<headers>
<xss-protection block="false"/>
</headers>
</http>
----
2020-07-10 10:08:02 -04:00
.Kotlin
[source,kotlin,role="secondary"]
----
@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
// ...
http {
headers {
xssProtection {
block = false
}
}
}
}
}
----
====
2018-03-06 11:57:57 -05:00
2019-11-07 11:55:27 -05:00
[[servlet-headers-csp]]
2019-10-28 17:00:51 -04:00
== Content Security Policy (CSP)
2018-03-06 11:57:57 -05:00
2021-07-30 17:56:54 -04:00
Spring Security does not add xref:overview/features/exploits/headers.adoc#headers-csp[Content Security Policy] by default, because a reasonable default is impossible to know without context of the application.
2019-11-07 11:55:27 -05:00
The web application author must declare the security policy(s) to enforce and/or monitor for the protected resources.
2018-03-06 11:57:57 -05:00
2019-11-07 11:55:27 -05:00
For example, given the following security policy:
2018-03-06 11:57:57 -05:00
2019-11-07 11:55:27 -05:00
.Content Security Policy Example
====
[source,http]
2018-03-06 11:57:57 -05:00
----
2019-11-07 11:55:27 -05:00
Content-Security-Policy: script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/
2018-03-06 11:57:57 -05:00
----
2019-11-07 11:55:27 -05:00
====
2018-03-06 11:57:57 -05:00
2020-07-10 10:08:02 -04:00
You can enable the CSP header as shown below:
2018-03-06 11:57:57 -05:00
2020-07-10 10:08:02 -04:00
.Content Security Policy
2019-11-07 11:55:27 -05:00
====
2020-07-10 10:08:02 -04:00
.Java
[source,java,role="primary"]
2018-03-06 11:57:57 -05:00
----
2019-11-07 11:55:27 -05:00
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
2018-03-06 11:57:57 -05:00
2019-11-07 11:55:27 -05:00
@Override
protected void configure(HttpSecurity http) {
http
// ...
2020-01-10 07:10:36 -05:00
.headers(headers -> headers
.contentSecurityPolicy(csp -> csp
.policyDirectives("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/")
)
2019-11-07 11:55:27 -05:00
);
}
}
2018-03-06 11:57:57 -05:00
----
2020-07-10 10:08:02 -04:00
.XML
[source,xml,role="secondary"]
2018-03-06 11:57:57 -05:00
----
<http>
<!-- ... -->
<headers>
<content-security-policy
policy-directives="script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/" />
</headers>
</http>
----
2020-07-10 10:08:02 -04:00
.Kotlin
[source,kotlin,role="secondary"]
----
@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http {
// ...
headers {
contentSecurityPolicy {
policyDirectives = "script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/"
}
}
}
}
}
----
2019-11-07 11:55:27 -05:00
====
2020-07-10 10:08:02 -04:00
To enable the CSP `report-only` header, provide the following configuration:
2019-11-07 11:55:27 -05:00
2020-07-10 10:08:02 -04:00
.Content Security Policy Report Only
2019-11-07 11:55:27 -05:00
====
2020-07-10 10:08:02 -04:00
.Java
[source,java,role="primary"]
2019-11-07 11:55:27 -05:00
----
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
2018-03-06 11:57:57 -05:00
2019-11-07 11:55:27 -05:00
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
2020-01-10 07:10:36 -05:00
.headers(headers -> headers
.contentSecurityPolicy(csp -> csp
.policyDirectives("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/")
.reportOnly()
)
2019-11-07 11:55:27 -05:00
);
}
}
----
2020-07-10 10:08:02 -04:00
.XML
[source,xml,role="secondary"]
2018-03-06 11:57:57 -05:00
----
<http>
<!-- ... -->
<headers>
<content-security-policy
policy-directives="script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/"
report-only="true" />
</headers>
</http>
----
2020-07-10 10:08:02 -04:00
.Kotlin
[source,kotlin,role="secondary"]
----
@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http {
// ...
headers {
contentSecurityPolicy {
policyDirectives = "script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/"
reportOnly = true
}
}
}
}
}
----
2019-11-07 11:55:27 -05:00
====
2018-03-06 11:57:57 -05:00
2019-11-07 11:55:27 -05:00
[[servlet-headers-referrer]]
== Referrer Policy
2018-03-06 11:57:57 -05:00
2021-07-30 17:56:54 -04:00
Spring Security does not add xref:overview/features/exploits/headers.adoc#headers-referrer[Referrer Policy] headers by default.
2020-07-10 10:08:02 -04:00
You can enable the Referrer Policy header using the configuration as shown below:
2018-03-06 11:57:57 -05:00
2020-07-10 10:08:02 -04:00
.Referrer Policy
2019-11-07 11:55:27 -05:00
====
2020-07-10 10:08:02 -04:00
.Java
[source,java,role="primary"]
2018-03-06 11:57:57 -05:00
----
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
2019-11-07 11:55:27 -05:00
@Override
protected void configure(HttpSecurity http) {
http
// ...
2020-01-10 07:10:36 -05:00
.headers(headers -> headers
.referrerPolicy(referrer -> referrer
.policy(ReferrerPolicy.SAME_ORIGIN)
)
2019-11-07 11:55:27 -05:00
);
}
2018-03-06 11:57:57 -05:00
}
----
2020-07-10 10:08:02 -04:00
.XML
[source,xml,role="secondary"]
2018-03-06 11:57:57 -05:00
----
<http>
<!-- ... -->
<headers>
<referrer-policy policy="same-origin" />
</headers>
</http>
----
2020-07-10 10:08:02 -04:00
.Kotlin
[source,kotlin,role="secondary"]
----
@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http {
// ...
headers {
referrerPolicy {
policy = ReferrerPolicy.SAME_ORIGIN
}
}
}
}
}
----
====
2018-03-06 11:57:57 -05:00
2019-11-07 11:55:27 -05:00
[[servlet-headers-feature]]
2019-10-28 17:00:51 -04:00
== Feature Policy
2018-08-15 16:05:10 -04:00
2021-07-30 17:56:54 -04:00
Spring Security does not add xref:overview/features/exploits/headers.adoc#headers-feature[Feature Policy] headers by default.
2019-11-07 11:55:27 -05:00
The following `Feature-Policy` header:
2018-08-15 16:05:10 -04:00
2019-11-07 11:55:27 -05:00
.Feature-Policy Example
====
2018-08-15 16:05:10 -04:00
[source]
----
Feature-Policy: geolocation 'self'
----
2019-11-07 11:55:27 -05:00
====
2018-08-15 16:05:10 -04:00
2020-07-10 10:08:02 -04:00
can enable the Feature Policy header using the configuration shown below:
2018-08-15 16:05:10 -04:00
2020-07-10 10:08:02 -04:00
.Feature-Policy
2019-11-07 11:55:27 -05:00
====
2020-07-10 10:08:02 -04:00
.Java
[source,java,role="primary"]
2019-11-07 11:55:27 -05:00
----
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
2020-01-10 07:10:36 -05:00
.headers(headers -> headers
.featurePolicy("geolocation 'self'")
2019-11-07 11:55:27 -05:00
);
}
}
----
2018-08-15 16:05:10 -04:00
2020-07-10 10:08:02 -04:00
.XML
[source,xml,role="secondary"]
2018-08-15 16:05:10 -04:00
----
<http>
<!-- ... -->
<headers>
<feature-policy policy-directives="geolocation 'self'" />
</headers>
</http>
----
2020-07-10 10:08:02 -04:00
.Kotlin
[source,kotlin,role="secondary"]
----
@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http {
// ...
headers {
featurePolicy("geolocation 'self'")
}
}
}
}
----
2019-11-07 11:55:27 -05:00
====
2018-08-15 16:05:10 -04:00
2020-12-04 17:00:09 -05:00
[[servlet-headers-permissions]]
== Permissions Policy
2021-07-30 17:56:54 -04:00
Spring Security does not add xref:overview/features/exploits/headers.adoc#headers-permissions[Permissions Policy] headers by default.
2020-12-04 17:00:09 -05:00
The following `Permissions-Policy` header:
.Permissions-Policy Example
====
[source]
----
Permissions-Policy: geolocation=(self)
----
====
can enable the Permissions Policy header using the configuration shown below:
.Permissions-Policy
====
.Java
[source,java,role="primary"]
----
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
.headers(headers -> headers
.permissionsPolicy(permissions -> permissions
.policy("geolocation=(self)")
)
);
}
}
----
.XML
[source,xml,role="secondary"]
----
<http>
<!-- ... -->
<headers>
<permissions-policy policy="geolocation=(self)" />
</headers>
</http>
----
.Kotlin
[source,kotlin,role="secondary"]
----
@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http {
// ...
headers {
permissionPolicy {
policy = "geolocation=(self)"
}
}
}
}
}
----
====
2019-11-07 11:55:27 -05:00
[[servlet-headers-clear-site-data]]
2019-10-28 17:00:51 -04:00
== Clear Site Data
2019-09-20 15:02:06 -04:00
2021-07-30 17:56:54 -04:00
Spring Security does not add xref:overview/features/exploits/headers.adoc#headers-clear-site-data[Clear-Site-Data] headers by default.
2019-11-07 11:55:27 -05:00
The following Clear-Site-Data header:
2019-09-20 15:02:06 -04:00
2019-11-07 11:55:27 -05:00
.Clear-Site-Data Example
====
2019-09-20 15:02:06 -04:00
----
2019-11-07 11:55:27 -05:00
Clear-Site-Data: "cache", "cookies"
2019-09-20 15:02:06 -04:00
----
2019-11-07 11:55:27 -05:00
====
2019-09-20 15:02:06 -04:00
2019-11-07 11:55:27 -05:00
can be sent on log out with the following configuration:
2019-09-20 15:02:06 -04:00
2020-07-10 10:08:02 -04:00
.Clear-Site-Data
2019-11-07 11:55:27 -05:00
====
2020-07-10 10:08:02 -04:00
.Java
[source,java,role="primary"]
2019-09-20 15:02:06 -04:00
----
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
2019-11-07 11:55:27 -05:00
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
.logout()
.addLogoutHandler(new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(CACHE, COOKIES)));
}
2019-09-20 15:02:06 -04:00
}
----
2020-07-10 10:08:02 -04:00
.Kotlin
[source,kotlin,role="secondary"]
----
@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http {
// ...
logout {
addLogoutHandler(HeaderWriterLogoutHandler(ClearSiteDataHeaderWriter(CACHE, COOKIES)))
}
}
}
}
----
2019-11-07 11:55:27 -05:00
====
2019-09-20 15:02:06 -04:00
2019-11-07 11:55:27 -05:00
[[servlet-headers-custom]]
2019-10-28 17:00:51 -04:00
== Custom Headers
2018-03-06 11:57:57 -05:00
Spring Security has mechanisms to make it convenient to add the more common security headers to your application.
However, it also provides hooks to enable adding custom headers.
2019-11-07 11:55:27 -05:00
[[servlet-headers-static]]
2019-10-28 17:00:51 -04:00
=== Static Headers
2018-03-06 11:57:57 -05:00
There may be times you wish to inject custom security headers into your application that are not supported out of the box.
For example, given the following custom security header:
[source]
----
X-Custom-Security-Header: header-value
----
2020-07-10 10:08:02 -04:00
The headers could be added to the response using the following Configuration:
2019-11-07 11:55:27 -05:00
2020-07-10 10:08:02 -04:00
.StaticHeadersWriter
2019-11-07 11:55:27 -05:00
====
2020-07-10 10:08:02 -04:00
.Java
[source,java,role="primary"]
2019-11-07 11:55:27 -05:00
----
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
2020-01-10 07:10:36 -05:00
.headers(headers -> headers
.addHeaderWriter(new StaticHeadersWriter("X-Custom-Security-Header","header-value"))
2019-11-07 11:55:27 -05:00
);
}
}
----
2018-03-06 11:57:57 -05:00
2020-07-10 10:08:02 -04:00
.XML
[source,xml,role="secondary"]
2018-03-06 11:57:57 -05:00
----
<http>
<!-- ... -->
<headers>
<header name="X-Custom-Security-Header" value="header-value"/>
</headers>
</http>
----
2019-11-07 11:55:27 -05:00
2020-07-10 10:08:02 -04:00
.Kotlin
[source,kotlin,role="secondary"]
----
@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http {
// ...
headers {
addHeaderWriter(StaticHeadersWriter("X-Custom-Security-Header","header-value"))
}
}
}
}
----
====
2019-11-07 11:55:27 -05:00
[[servlet-headers-writer]]
=== Headers Writer
When the namespace or Java configuration does not support the headers you want, you can create a custom `HeadersWriter` instance or even provide a custom implementation of the `HeadersWriter`.
2018-03-06 11:57:57 -05:00
2019-11-07 11:55:27 -05:00
Let's take a look at an example of using an custom instance of `XFrameOptionsHeaderWriter`.
2020-07-10 10:08:02 -04:00
If you wanted to explicitly configure <<servlet-headers-frame-options>> it could be done with the following Configuration:
2018-03-06 11:57:57 -05:00
2020-07-10 10:08:02 -04:00
.Headers Writer
2019-11-07 11:55:27 -05:00
====
2020-07-10 10:08:02 -04:00
.Java
[source,java,role="primary"]
2018-03-06 11:57:57 -05:00
----
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
2019-11-07 11:55:27 -05:00
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
2020-01-10 07:10:36 -05:00
.headers(headers -> headers
.addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN))
2019-11-07 11:55:27 -05:00
);
}
2018-03-06 11:57:57 -05:00
}
----
2020-07-10 10:08:02 -04:00
.XML
[source,xml,role="secondary"]
2018-03-06 11:57:57 -05:00
----
<http>
<!-- ... -->
<headers>
<header ref="frameOptionsWriter"/>
</headers>
</http>
<!-- Requires the c-namespace.
2019-03-20 00:53:23 -04:00
See https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-c-namespace
2018-03-06 11:57:57 -05:00
-->
<beans:bean id="frameOptionsWriter"
class="org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter"
c:frameOptionsMode="SAMEORIGIN"/>
----
2020-07-10 10:08:02 -04:00
.Kotlin
[source,kotlin,role="secondary"]
----
@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http {
// ...
headers {
addHeaderWriter(XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN))
}
}
}
}
----
2019-11-07 11:55:27 -05:00
====
2018-03-06 11:57:57 -05:00
2019-11-07 11:55:27 -05:00
[[headers-delegatingrequestmatcherheaderwriter]]
=== DelegatingRequestMatcherHeaderWriter
2018-03-06 11:57:57 -05:00
2019-11-07 11:55:27 -05:00
At times you may want to only write a header for certain requests.
For example, perhaps you want to only protect your log in page from being framed.
You could use the `DelegatingRequestMatcherHeaderWriter` to do so.
2018-03-06 11:57:57 -05:00
2019-11-07 11:55:27 -05:00
An example of using `DelegatingRequestMatcherHeaderWriter` in Java Configuration can be seen below:
2018-03-06 11:57:57 -05:00
2019-11-07 11:55:27 -05:00
.DelegatingRequestMatcherHeaderWriter Java Configuration
====
2020-07-10 10:08:02 -04:00
.Java
[source,java,role="primary"]
2018-03-06 11:57:57 -05:00
----
@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
2019-11-07 11:55:27 -05:00
@Override
protected void configure(HttpSecurity http) throws Exception {
RequestMatcher matcher = new AntPathRequestMatcher("/login");
DelegatingRequestMatcherHeaderWriter headerWriter =
new DelegatingRequestMatcherHeaderWriter(matcher,new XFrameOptionsHeaderWriter());
http
// ...
2020-01-10 07:10:36 -05:00
.headers(headers -> headers
.frameOptions(frameOptions -> frameOptions.disable())
.addHeaderWriter(headerWriter)
2019-11-07 11:55:27 -05:00
);
}
2018-03-06 11:57:57 -05:00
}
----
2020-07-10 10:08:02 -04:00
.XML
[source,xml,role="secondary"]
2018-03-06 11:57:57 -05:00
----
<http>
<!-- ... -->
<headers>
<frame-options disabled="true"/>
<header ref="headerWriter"/>
</headers>
</http>
<beans:bean id="headerWriter"
class="org.springframework.security.web.header.writers.DelegatingRequestMatcherHeaderWriter">
<beans:constructor-arg>
<bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher"
c:pattern="/login"/>
</beans:constructor-arg>
<beans:constructor-arg>
<beans:bean
class="org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter"/>
</beans:constructor-arg>
</beans:bean>
----
2020-07-10 10:08:02 -04:00
.Kotlin
[source,kotlin,role="secondary"]
----
@EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
val matcher: RequestMatcher = AntPathRequestMatcher("/login")
val headerWriter = DelegatingRequestMatcherHeaderWriter(matcher, XFrameOptionsHeaderWriter())
http {
headers {
frameOptions {
disable()
}
addHeaderWriter(headerWriter)
}
}
}
}
----
====