mirror of
				https://github.com/spring-projects/spring-security.git
				synced 2025-11-04 00:28:54 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			1150 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			1150 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
[[servlet-headers]]
 | 
						|
= Security HTTP Response Headers
 | 
						|
 | 
						|
xref:features/exploits/headers.adoc#headers[Security HTTP Response Headers] can be used to increase the security of web applications.
 | 
						|
This section is dedicated to servlet based support for Security HTTP Response Headers.
 | 
						|
 | 
						|
[[servlet-headers-default]]
 | 
						|
== Default Security Headers
 | 
						|
 | 
						|
Spring Security provides a xref:features/exploits/headers.adoc#headers-default[default set of Security HTTP Response Headers] to provide secure defaults.
 | 
						|
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.
 | 
						|
For example, assume that you want the defaults except you wish to specify `SAMEORIGIN` for <<servlet-headers-frame-options,X-Frame-Options>>.
 | 
						|
 | 
						|
You can easily do this with the following Configuration:
 | 
						|
 | 
						|
.Customize Default Security Headers
 | 
						|
====
 | 
						|
.Java
 | 
						|
[source,java,role="primary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
public class WebSecurityConfig extends
 | 
						|
		WebSecurityConfigurerAdapter {
 | 
						|
 | 
						|
	@Override
 | 
						|
	protected void configure(HttpSecurity http) {
 | 
						|
		http
 | 
						|
			// ...
 | 
						|
			.headers(headers -> headers
 | 
						|
				.frameOptions(frameOptions -> frameOptions
 | 
						|
					.sameOrigin()
 | 
						|
				)
 | 
						|
			);
 | 
						|
	}
 | 
						|
}
 | 
						|
----
 | 
						|
 | 
						|
.XML
 | 
						|
[source,xml,role="secondary"]
 | 
						|
----
 | 
						|
<http>
 | 
						|
	<!-- ... -->
 | 
						|
 | 
						|
	<headers>
 | 
						|
		<frame-options policy="SAMEORIGIN" />
 | 
						|
	</headers>
 | 
						|
</http>
 | 
						|
----
 | 
						|
 | 
						|
.Kotlin
 | 
						|
[source,kotlin,role="secondary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
class SecurityConfig : WebSecurityConfigurerAdapter() {
 | 
						|
    override fun configure(http: HttpSecurity) {
 | 
						|
        http {
 | 
						|
            // ...
 | 
						|
            headers {
 | 
						|
                frameOptions {
 | 
						|
                    sameOrigin = true
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
----
 | 
						|
====
 | 
						|
 | 
						|
If you do not want the defaults to be added and want explicit control over what should be used, you can disable the defaults.
 | 
						|
An example is provided below:
 | 
						|
 | 
						|
If you are using Spring Security's Configuration the following will only add xref:features/exploits/headers.adoc#headers-cache-control[Cache Control].
 | 
						|
 | 
						|
.Customize Cache Control Headers
 | 
						|
====
 | 
						|
.Java
 | 
						|
[source,java,role="primary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
public class WebSecurityConfig extends
 | 
						|
WebSecurityConfigurerAdapter {
 | 
						|
 | 
						|
	@Override
 | 
						|
	protected void configure(HttpSecurity http) throws Exception {
 | 
						|
		http
 | 
						|
			// ...
 | 
						|
			.headers(headers -> headers
 | 
						|
				// do not use any default headers unless explicitly listed
 | 
						|
				.defaultsDisabled()
 | 
						|
				.cacheControl(withDefaults())
 | 
						|
			);
 | 
						|
	}
 | 
						|
}
 | 
						|
----
 | 
						|
 | 
						|
.XML
 | 
						|
[source,xml,role="secondary"]
 | 
						|
----
 | 
						|
<http>
 | 
						|
	<!-- ... -->
 | 
						|
 | 
						|
	<headers defaults-disabled="true">
 | 
						|
		<cache-control/>
 | 
						|
	</headers>
 | 
						|
</http>
 | 
						|
----
 | 
						|
 | 
						|
.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 {
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
----
 | 
						|
====
 | 
						|
 | 
						|
If necessary, you can disable all of the HTTP Security response headers with the following Configuration:
 | 
						|
 | 
						|
.Disable All HTTP Security Headers
 | 
						|
====
 | 
						|
.Java
 | 
						|
[source,java,role="primary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
public class WebSecurityConfig extends
 | 
						|
WebSecurityConfigurerAdapter {
 | 
						|
 | 
						|
	@Override
 | 
						|
	protected void configure(HttpSecurity http) throws Exception {
 | 
						|
		http
 | 
						|
			// ...
 | 
						|
			.headers(headers -> headers.disable());
 | 
						|
	}
 | 
						|
}
 | 
						|
----
 | 
						|
 | 
						|
.XML
 | 
						|
[source,xml,role="secondary"]
 | 
						|
----
 | 
						|
<http>
 | 
						|
	<!-- ... -->
 | 
						|
 | 
						|
	<headers disabled="true" />
 | 
						|
</http>
 | 
						|
----
 | 
						|
 | 
						|
.Kotlin
 | 
						|
[source,kotlin,role="secondary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
class SecurityConfig : WebSecurityConfigurerAdapter() {
 | 
						|
    override fun configure(http: HttpSecurity) {
 | 
						|
        http {
 | 
						|
            // ...
 | 
						|
            headers {
 | 
						|
                disable()
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
----
 | 
						|
====
 | 
						|
 | 
						|
[[servlet-headers-cache-control]]
 | 
						|
== Cache Control
 | 
						|
 | 
						|
Spring Security includes xref:features/exploits/headers.adoc#headers-cache-control[Cache Control] headers by default.
 | 
						|
 | 
						|
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.
 | 
						|
 | 
						|
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
 | 
						|
 | 
						|
If necessary, you can also disable Spring Security's cache control HTTP response headers.
 | 
						|
 | 
						|
.Cache Control Disabled
 | 
						|
====
 | 
						|
.Java
 | 
						|
[source,java,role="primary"]
 | 
						|
----
 | 
						|
@Configuration
 | 
						|
@EnableWebSecurity
 | 
						|
public class WebSecurityConfig extends
 | 
						|
WebSecurityConfigurerAdapter {
 | 
						|
 | 
						|
	@Override
 | 
						|
	protected void configure(HttpSecurity http) {
 | 
						|
		http
 | 
						|
			// ...
 | 
						|
			.headers(headers -> headers
 | 
						|
				.cacheControl(cache -> cache.disable())
 | 
						|
			);
 | 
						|
	}
 | 
						|
}
 | 
						|
----
 | 
						|
 | 
						|
.XML
 | 
						|
[source,xml,role="secondary"]
 | 
						|
----
 | 
						|
<http>
 | 
						|
	<!-- ... -->
 | 
						|
 | 
						|
	<headers>
 | 
						|
		<cache-control disabled="true"/>
 | 
						|
	</headers>
 | 
						|
</http>
 | 
						|
----
 | 
						|
 | 
						|
.Kotlin
 | 
						|
[source,kotlin,role="secondary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
class SecurityConfig : WebSecurityConfigurerAdapter() {
 | 
						|
 | 
						|
    override fun configure(http: HttpSecurity) {
 | 
						|
       http {
 | 
						|
            headers {
 | 
						|
                cacheControl {
 | 
						|
                    disable()
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
----
 | 
						|
====
 | 
						|
 | 
						|
[[servlet-headers-content-type-options]]
 | 
						|
== Content Type Options
 | 
						|
 | 
						|
Spring Security includes xref:features/exploits/headers.adoc#headers-content-type-options[Content-Type] headers by default.
 | 
						|
However, you can disable it with:
 | 
						|
 | 
						|
.Content Type Options Disabled
 | 
						|
====
 | 
						|
.Java
 | 
						|
[source,java,role="primary"]
 | 
						|
----
 | 
						|
@Configuration
 | 
						|
@EnableWebSecurity
 | 
						|
public class WebSecurityConfig extends
 | 
						|
		WebSecurityConfigurerAdapter {
 | 
						|
 | 
						|
	@Override
 | 
						|
	protected void configure(HttpSecurity http) {
 | 
						|
		http
 | 
						|
			// ...
 | 
						|
			.headers(headers -> headers
 | 
						|
				.contentTypeOptions(contentTypeOptions -> contentTypeOptions.disable())
 | 
						|
			);
 | 
						|
	}
 | 
						|
}
 | 
						|
----
 | 
						|
 | 
						|
.XML
 | 
						|
[source,xml,role="secondary"]
 | 
						|
----
 | 
						|
<http>
 | 
						|
	<!-- ... -->
 | 
						|
 | 
						|
	<headers>
 | 
						|
		<content-type-options disabled="true"/>
 | 
						|
	</headers>
 | 
						|
</http>
 | 
						|
----
 | 
						|
 | 
						|
.Kotlin
 | 
						|
[source,kotlin,role="secondary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
class SecurityConfig : WebSecurityConfigurerAdapter() {
 | 
						|
 | 
						|
    override fun configure(http: HttpSecurity) {
 | 
						|
       http {
 | 
						|
            headers {
 | 
						|
                contentTypeOptions {
 | 
						|
                    disable()
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
----
 | 
						|
====
 | 
						|
 | 
						|
[[servlet-headers-hsts]]
 | 
						|
== HTTP Strict Transport Security (HSTS)
 | 
						|
 | 
						|
Spring Security provides the xref:features/exploits/headers.adoc#headers-hsts[Strict Transport Security] header by default.
 | 
						|
However, you can customize the results explicitly.
 | 
						|
For example, the following is an example of explicitly providing HSTS:
 | 
						|
 | 
						|
.Strict Transport Security
 | 
						|
====
 | 
						|
.Java
 | 
						|
[source,java,role="primary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
public class WebSecurityConfig extends
 | 
						|
WebSecurityConfigurerAdapter {
 | 
						|
 | 
						|
	@Override
 | 
						|
	protected void configure(HttpSecurity http) throws Exception {
 | 
						|
		http
 | 
						|
			// ...
 | 
						|
			.headers(headers -> headers
 | 
						|
				.httpStrictTransportSecurity(hsts -> hsts
 | 
						|
					.includeSubDomains(true)
 | 
						|
					.preload(true)
 | 
						|
					.maxAgeInSeconds(31536000)
 | 
						|
				)
 | 
						|
			);
 | 
						|
	}
 | 
						|
}
 | 
						|
----
 | 
						|
 | 
						|
.XML
 | 
						|
[source,xml,role="secondary"]
 | 
						|
----
 | 
						|
<http>
 | 
						|
	<!-- ... -->
 | 
						|
 | 
						|
	<headers>
 | 
						|
		<hsts
 | 
						|
			include-subdomains="true"
 | 
						|
			max-age-seconds="31536000"
 | 
						|
			preload="true" />
 | 
						|
	</headers>
 | 
						|
</http>
 | 
						|
----
 | 
						|
 | 
						|
.Kotlin
 | 
						|
[source,kotlin,role="secondary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
class SecurityConfig : WebSecurityConfigurerAdapter() {
 | 
						|
 | 
						|
    override fun configure(http: HttpSecurity) {
 | 
						|
        http {
 | 
						|
            headers {
 | 
						|
                httpStrictTransportSecurity {
 | 
						|
                    includeSubDomains = true
 | 
						|
                    preload = true
 | 
						|
                    maxAgeInSeconds = 31536000
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
----
 | 
						|
====
 | 
						|
 | 
						|
[[servlet-headers-hpkp]]
 | 
						|
== HTTP Public Key Pinning (HPKP)
 | 
						|
For passivity reasons, Spring Security provides servlet support for xref:features/exploits/headers.adoc#headers-hpkp[HTTP Public Key Pinning] but it is xref:features/exploits/headers.adoc#headers-hpkp-deprecated[no longer recommended].
 | 
						|
 | 
						|
You can enable HPKP headers with the following Configuration:
 | 
						|
 | 
						|
.HTTP Public Key Pinning
 | 
						|
====
 | 
						|
.Java
 | 
						|
[source,java,role="primary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
public class WebSecurityConfig extends
 | 
						|
WebSecurityConfigurerAdapter {
 | 
						|
 | 
						|
	@Override
 | 
						|
	protected void configure(HttpSecurity http) throws Exception {
 | 
						|
		http
 | 
						|
			// ...
 | 
						|
			.headers(headers -> headers
 | 
						|
				.httpPublicKeyPinning(hpkp -> hpkp
 | 
						|
					.includeSubDomains(true)
 | 
						|
					.reportUri("https://example.net/pkp-report")
 | 
						|
					.addSha256Pins("d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=", "E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=")
 | 
						|
				)
 | 
						|
			);
 | 
						|
	}
 | 
						|
}
 | 
						|
----
 | 
						|
.XML
 | 
						|
[source,xml,role="secondary"]
 | 
						|
----
 | 
						|
<http>
 | 
						|
	<!-- ... -->
 | 
						|
 | 
						|
	<headers>
 | 
						|
		<hpkp
 | 
						|
			include-subdomains="true"
 | 
						|
			report-uri="https://example.net/pkp-report">
 | 
						|
			<pins>
 | 
						|
				<pin algorithm="sha256">d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=</pin>
 | 
						|
				<pin algorithm="sha256">E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=</pin>
 | 
						|
			</pins>
 | 
						|
		</hpkp>
 | 
						|
	</headers>
 | 
						|
</http>
 | 
						|
----
 | 
						|
 | 
						|
.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")
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
----
 | 
						|
====
 | 
						|
 | 
						|
[[servlet-headers-frame-options]]
 | 
						|
== X-Frame-Options
 | 
						|
 | 
						|
By default, Spring Security disables rendering within an iframe using xref:features/exploits/headers.adoc#headers-frame-options[X-Frame-Options].
 | 
						|
 | 
						|
You can customize frame options to use the same origin within a Configuration using the following:
 | 
						|
 | 
						|
.X-Frame-Options: SAMEORIGIN
 | 
						|
====
 | 
						|
.Java
 | 
						|
[source,java,role="primary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
public class WebSecurityConfig extends
 | 
						|
WebSecurityConfigurerAdapter {
 | 
						|
 | 
						|
	@Override
 | 
						|
	protected void configure(HttpSecurity http) throws Exception {
 | 
						|
		http
 | 
						|
			// ...
 | 
						|
			.headers(headers -> headers
 | 
						|
				.frameOptions(frameOptions -> frameOptions
 | 
						|
					.sameOrigin()
 | 
						|
				)
 | 
						|
			);
 | 
						|
	}
 | 
						|
}
 | 
						|
----
 | 
						|
 | 
						|
.XML
 | 
						|
[source,xml,role="secondary"]
 | 
						|
----
 | 
						|
<http>
 | 
						|
	<!-- ... -->
 | 
						|
 | 
						|
	<headers>
 | 
						|
		<frame-options
 | 
						|
		policy="SAMEORIGIN" />
 | 
						|
	</headers>
 | 
						|
</http>
 | 
						|
----
 | 
						|
 | 
						|
 | 
						|
.Kotlin
 | 
						|
[source,kotlin,role="secondary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
class SecurityConfig : WebSecurityConfigurerAdapter() {
 | 
						|
 | 
						|
    override fun configure(http: HttpSecurity) {
 | 
						|
        http {
 | 
						|
            headers {
 | 
						|
                frameOptions {
 | 
						|
                    sameOrigin = true
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
----
 | 
						|
====
 | 
						|
 | 
						|
[[servlet-headers-xss-protection]]
 | 
						|
== X-XSS-Protection
 | 
						|
 | 
						|
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.
 | 
						|
For example, the following Configuration specifies that Spring Security should no longer instruct browsers to block the content:
 | 
						|
 | 
						|
.X-XSS-Protection Customization
 | 
						|
====
 | 
						|
.Java
 | 
						|
[source,java,role="primary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
public class WebSecurityConfig extends
 | 
						|
WebSecurityConfigurerAdapter {
 | 
						|
 | 
						|
	@Override
 | 
						|
	protected void configure(HttpSecurity http) throws Exception {
 | 
						|
		http
 | 
						|
			// ...
 | 
						|
			.headers(headers -> headers
 | 
						|
				.xssProtection(xss -> xss
 | 
						|
					.block(false)
 | 
						|
				)
 | 
						|
			);
 | 
						|
	}
 | 
						|
}
 | 
						|
----
 | 
						|
 | 
						|
.XML
 | 
						|
[source,xml,role="secondary"]
 | 
						|
----
 | 
						|
<http>
 | 
						|
	<!-- ... -->
 | 
						|
 | 
						|
	<headers>
 | 
						|
		<xss-protection block="false"/>
 | 
						|
	</headers>
 | 
						|
</http>
 | 
						|
----
 | 
						|
 | 
						|
.Kotlin
 | 
						|
[source,kotlin,role="secondary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
class SecurityConfig : WebSecurityConfigurerAdapter() {
 | 
						|
 | 
						|
    override fun configure(http: HttpSecurity) {
 | 
						|
        // ...
 | 
						|
        http {
 | 
						|
            headers {
 | 
						|
                xssProtection {
 | 
						|
                    block = false
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
----
 | 
						|
====
 | 
						|
 | 
						|
[[servlet-headers-csp]]
 | 
						|
== Content Security Policy (CSP)
 | 
						|
 | 
						|
Spring Security does not add xref:features/exploits/headers.adoc#headers-csp[Content Security Policy] by default, because a reasonable default is impossible to know without context of the application.
 | 
						|
The web application author must declare the security policy(s) to enforce and/or monitor for the protected resources.
 | 
						|
 | 
						|
For example, given the following security policy:
 | 
						|
 | 
						|
.Content Security Policy Example
 | 
						|
====
 | 
						|
[source,http]
 | 
						|
----
 | 
						|
Content-Security-Policy: script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/
 | 
						|
----
 | 
						|
====
 | 
						|
 | 
						|
You can enable the CSP header as shown below:
 | 
						|
 | 
						|
.Content Security Policy
 | 
						|
====
 | 
						|
.Java
 | 
						|
[source,java,role="primary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
public class WebSecurityConfig extends
 | 
						|
WebSecurityConfigurerAdapter {
 | 
						|
 | 
						|
	@Override
 | 
						|
	protected void configure(HttpSecurity http) {
 | 
						|
		http
 | 
						|
			// ...
 | 
						|
			.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/")
 | 
						|
				)
 | 
						|
			);
 | 
						|
	}
 | 
						|
}
 | 
						|
----
 | 
						|
 | 
						|
.XML
 | 
						|
[source,xml,role="secondary"]
 | 
						|
----
 | 
						|
<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>
 | 
						|
----
 | 
						|
 | 
						|
.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/"
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
----
 | 
						|
====
 | 
						|
 | 
						|
To enable the CSP `report-only` header, provide the following configuration:
 | 
						|
 | 
						|
.Content Security Policy Report Only
 | 
						|
====
 | 
						|
.Java
 | 
						|
[source,java,role="primary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
public class WebSecurityConfig extends
 | 
						|
		WebSecurityConfigurerAdapter {
 | 
						|
 | 
						|
	@Override
 | 
						|
	protected void configure(HttpSecurity http) throws Exception {
 | 
						|
		http
 | 
						|
			// ...
 | 
						|
			.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()
 | 
						|
				)
 | 
						|
			);
 | 
						|
	}
 | 
						|
}
 | 
						|
----
 | 
						|
 | 
						|
.XML
 | 
						|
[source,xml,role="secondary"]
 | 
						|
----
 | 
						|
<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>
 | 
						|
----
 | 
						|
 | 
						|
.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
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
----
 | 
						|
====
 | 
						|
 | 
						|
[[servlet-headers-referrer]]
 | 
						|
== Referrer Policy
 | 
						|
 | 
						|
Spring Security does not add xref:features/exploits/headers.adoc#headers-referrer[Referrer Policy] headers by default.
 | 
						|
You can enable the Referrer Policy header using the configuration as shown below:
 | 
						|
 | 
						|
.Referrer Policy
 | 
						|
====
 | 
						|
.Java
 | 
						|
[source,java,role="primary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
public class WebSecurityConfig extends
 | 
						|
WebSecurityConfigurerAdapter {
 | 
						|
 | 
						|
	@Override
 | 
						|
	protected void configure(HttpSecurity http) {
 | 
						|
		http
 | 
						|
			// ...
 | 
						|
			.headers(headers -> headers
 | 
						|
				.referrerPolicy(referrer -> referrer
 | 
						|
					.policy(ReferrerPolicy.SAME_ORIGIN)
 | 
						|
				)
 | 
						|
			);
 | 
						|
	}
 | 
						|
}
 | 
						|
----
 | 
						|
 | 
						|
.XML
 | 
						|
[source,xml,role="secondary"]
 | 
						|
----
 | 
						|
<http>
 | 
						|
	<!-- ... -->
 | 
						|
 | 
						|
	<headers>
 | 
						|
		<referrer-policy policy="same-origin" />
 | 
						|
	</headers>
 | 
						|
</http>
 | 
						|
----
 | 
						|
 | 
						|
.Kotlin
 | 
						|
[source,kotlin,role="secondary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
class SecurityConfig : WebSecurityConfigurerAdapter() {
 | 
						|
 | 
						|
    override fun configure(http: HttpSecurity) {
 | 
						|
        http {
 | 
						|
            // ...
 | 
						|
            headers {
 | 
						|
                referrerPolicy {
 | 
						|
                    policy = ReferrerPolicy.SAME_ORIGIN
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
----
 | 
						|
====
 | 
						|
 | 
						|
[[servlet-headers-feature]]
 | 
						|
== Feature Policy
 | 
						|
 | 
						|
Spring Security does not add xref:features/exploits/headers.adoc#headers-feature[Feature Policy] headers by default.
 | 
						|
The following `Feature-Policy` header:
 | 
						|
 | 
						|
.Feature-Policy Example
 | 
						|
====
 | 
						|
[source]
 | 
						|
----
 | 
						|
Feature-Policy: geolocation 'self'
 | 
						|
----
 | 
						|
====
 | 
						|
 | 
						|
can enable the Feature Policy header using the configuration shown below:
 | 
						|
 | 
						|
.Feature-Policy
 | 
						|
====
 | 
						|
.Java
 | 
						|
[source,java,role="primary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
public class WebSecurityConfig extends
 | 
						|
WebSecurityConfigurerAdapter {
 | 
						|
 | 
						|
	@Override
 | 
						|
	protected void configure(HttpSecurity http) throws Exception {
 | 
						|
		http
 | 
						|
			// ...
 | 
						|
			.headers(headers -> headers
 | 
						|
				.featurePolicy("geolocation 'self'")
 | 
						|
			);
 | 
						|
	}
 | 
						|
}
 | 
						|
----
 | 
						|
 | 
						|
.XML
 | 
						|
[source,xml,role="secondary"]
 | 
						|
----
 | 
						|
<http>
 | 
						|
	<!-- ... -->
 | 
						|
 | 
						|
	<headers>
 | 
						|
		<feature-policy policy-directives="geolocation 'self'" />
 | 
						|
	</headers>
 | 
						|
</http>
 | 
						|
----
 | 
						|
 | 
						|
.Kotlin
 | 
						|
[source,kotlin,role="secondary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
class SecurityConfig : WebSecurityConfigurerAdapter() {
 | 
						|
 | 
						|
    override fun configure(http: HttpSecurity) {
 | 
						|
        http {
 | 
						|
            // ...
 | 
						|
            headers {
 | 
						|
                featurePolicy("geolocation 'self'")
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
----
 | 
						|
====
 | 
						|
 | 
						|
[[servlet-headers-permissions]]
 | 
						|
== Permissions Policy
 | 
						|
 | 
						|
Spring Security does not add xref:features/exploits/headers.adoc#headers-permissions[Permissions Policy] headers by default.
 | 
						|
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)"
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
----
 | 
						|
====
 | 
						|
 | 
						|
[[servlet-headers-clear-site-data]]
 | 
						|
== Clear Site Data
 | 
						|
 | 
						|
Spring Security does not add xref:features/exploits/headers.adoc#headers-clear-site-data[Clear-Site-Data] headers by default.
 | 
						|
The following Clear-Site-Data header:
 | 
						|
 | 
						|
.Clear-Site-Data Example
 | 
						|
====
 | 
						|
----
 | 
						|
Clear-Site-Data: "cache", "cookies"
 | 
						|
----
 | 
						|
====
 | 
						|
 | 
						|
can be sent on log out with the following configuration:
 | 
						|
 | 
						|
.Clear-Site-Data
 | 
						|
====
 | 
						|
.Java
 | 
						|
[source,java,role="primary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
public class WebSecurityConfig extends
 | 
						|
WebSecurityConfigurerAdapter {
 | 
						|
 | 
						|
	@Override
 | 
						|
	protected void configure(HttpSecurity http) throws Exception {
 | 
						|
		http
 | 
						|
			// ...
 | 
						|
			.logout()
 | 
						|
				.addLogoutHandler(new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(CACHE, COOKIES)));
 | 
						|
	}
 | 
						|
}
 | 
						|
----
 | 
						|
 | 
						|
.Kotlin
 | 
						|
[source,kotlin,role="secondary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
class SecurityConfig : WebSecurityConfigurerAdapter() {
 | 
						|
 | 
						|
    override fun configure(http: HttpSecurity) {
 | 
						|
        http {
 | 
						|
            // ...
 | 
						|
            logout {
 | 
						|
                addLogoutHandler(HeaderWriterLogoutHandler(ClearSiteDataHeaderWriter(CACHE, COOKIES)))
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
----
 | 
						|
====
 | 
						|
 | 
						|
[[servlet-headers-custom]]
 | 
						|
== Custom Headers
 | 
						|
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.
 | 
						|
 | 
						|
[[servlet-headers-static]]
 | 
						|
=== Static Headers
 | 
						|
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
 | 
						|
----
 | 
						|
 | 
						|
The headers could be added to the response using the following Configuration:
 | 
						|
 | 
						|
.StaticHeadersWriter
 | 
						|
====
 | 
						|
.Java
 | 
						|
[source,java,role="primary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
public class WebSecurityConfig extends
 | 
						|
WebSecurityConfigurerAdapter {
 | 
						|
 | 
						|
	@Override
 | 
						|
	protected void configure(HttpSecurity http) throws Exception {
 | 
						|
		http
 | 
						|
			// ...
 | 
						|
			.headers(headers -> headers
 | 
						|
				.addHeaderWriter(new StaticHeadersWriter("X-Custom-Security-Header","header-value"))
 | 
						|
			);
 | 
						|
	}
 | 
						|
}
 | 
						|
----
 | 
						|
 | 
						|
.XML
 | 
						|
[source,xml,role="secondary"]
 | 
						|
----
 | 
						|
<http>
 | 
						|
	<!-- ... -->
 | 
						|
 | 
						|
	<headers>
 | 
						|
		<header name="X-Custom-Security-Header" value="header-value"/>
 | 
						|
	</headers>
 | 
						|
</http>
 | 
						|
----
 | 
						|
 | 
						|
.Kotlin
 | 
						|
[source,kotlin,role="secondary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
class SecurityConfig : WebSecurityConfigurerAdapter() {
 | 
						|
 | 
						|
    override fun configure(http: HttpSecurity) {
 | 
						|
        http {
 | 
						|
            // ...
 | 
						|
            headers {
 | 
						|
                addHeaderWriter(StaticHeadersWriter("X-Custom-Security-Header","header-value"))
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
----
 | 
						|
====
 | 
						|
 | 
						|
[[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`.
 | 
						|
 | 
						|
Let's take a look at an example of using an custom instance of `XFrameOptionsHeaderWriter`.
 | 
						|
If you wanted to explicitly configure <<servlet-headers-frame-options>> it could be done with the following Configuration:
 | 
						|
 | 
						|
.Headers Writer
 | 
						|
====
 | 
						|
.Java
 | 
						|
[source,java,role="primary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
public class WebSecurityConfig extends
 | 
						|
WebSecurityConfigurerAdapter {
 | 
						|
 | 
						|
	@Override
 | 
						|
	protected void configure(HttpSecurity http) throws Exception {
 | 
						|
		http
 | 
						|
			// ...
 | 
						|
			.headers(headers -> headers
 | 
						|
				.addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN))
 | 
						|
			);
 | 
						|
	}
 | 
						|
}
 | 
						|
----
 | 
						|
 | 
						|
.XML
 | 
						|
[source,xml,role="secondary"]
 | 
						|
----
 | 
						|
<http>
 | 
						|
	<!-- ... -->
 | 
						|
 | 
						|
	<headers>
 | 
						|
		<header ref="frameOptionsWriter"/>
 | 
						|
	</headers>
 | 
						|
</http>
 | 
						|
<!-- Requires the c-namespace.
 | 
						|
See https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-c-namespace
 | 
						|
-->
 | 
						|
<beans:bean id="frameOptionsWriter"
 | 
						|
	class="org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter"
 | 
						|
	c:frameOptionsMode="SAMEORIGIN"/>
 | 
						|
----
 | 
						|
 | 
						|
.Kotlin
 | 
						|
[source,kotlin,role="secondary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
class SecurityConfig : WebSecurityConfigurerAdapter() {
 | 
						|
 | 
						|
    override fun configure(http: HttpSecurity) {
 | 
						|
        http {
 | 
						|
            // ...
 | 
						|
            headers {
 | 
						|
                addHeaderWriter(XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN))
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
----
 | 
						|
====
 | 
						|
 | 
						|
[[headers-delegatingrequestmatcherheaderwriter]]
 | 
						|
=== DelegatingRequestMatcherHeaderWriter
 | 
						|
 | 
						|
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.
 | 
						|
 | 
						|
An example of using `DelegatingRequestMatcherHeaderWriter` in Java Configuration can be seen below:
 | 
						|
 | 
						|
.DelegatingRequestMatcherHeaderWriter Java Configuration
 | 
						|
====
 | 
						|
.Java
 | 
						|
[source,java,role="primary"]
 | 
						|
----
 | 
						|
@EnableWebSecurity
 | 
						|
public class WebSecurityConfig extends
 | 
						|
WebSecurityConfigurerAdapter {
 | 
						|
 | 
						|
	@Override
 | 
						|
	protected void configure(HttpSecurity http) throws Exception {
 | 
						|
		RequestMatcher matcher = new AntPathRequestMatcher("/login");
 | 
						|
		DelegatingRequestMatcherHeaderWriter headerWriter =
 | 
						|
			new DelegatingRequestMatcherHeaderWriter(matcher,new XFrameOptionsHeaderWriter());
 | 
						|
		http
 | 
						|
			// ...
 | 
						|
			.headers(headers -> headers
 | 
						|
				.frameOptions(frameOptions -> frameOptions.disable())
 | 
						|
				.addHeaderWriter(headerWriter)
 | 
						|
			);
 | 
						|
	}
 | 
						|
}
 | 
						|
----
 | 
						|
 | 
						|
.XML
 | 
						|
[source,xml,role="secondary"]
 | 
						|
----
 | 
						|
<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>
 | 
						|
----
 | 
						|
 | 
						|
.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)
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
----
 | 
						|
====
 |