2
0

headers.adoc 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220
  1. [[servlet-headers]]
  2. = Security HTTP Response Headers
  3. You can use xref:features/exploits/headers.adoc#headers[Security HTTP Response Headers] to increase the security of web applications.
  4. This section is dedicated to servlet-based support for Security HTTP Response Headers.
  5. [[servlet-headers-default]]
  6. == Default Security Headers
  7. Spring Security provides a xref:features/exploits/headers.adoc#headers-default[default set of Security HTTP Response Headers] to provide secure defaults.
  8. While each of these headers are considered best practice, it should be noted that not all clients use the headers, so additional testing is encouraged.
  9. You can customize specific headers.
  10. For example, assume that you want the defaults but you wish to specify `SAMEORIGIN` for <<servlet-headers-frame-options,X-Frame-Options>>.
  11. You can do so with the following configuration:
  12. .Customize Default Security Headers
  13. ====
  14. .Java
  15. [source,java,role="primary"]
  16. ----
  17. @Configuration
  18. @EnableWebSecurity
  19. public class WebSecurityConfig {
  20. @Bean
  21. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  22. http
  23. // ...
  24. .headers(headers -> headers
  25. .frameOptions(frameOptions -> frameOptions
  26. .sameOrigin()
  27. )
  28. );
  29. return http.build();
  30. }
  31. }
  32. ----
  33. .XML
  34. [source,xml,role="secondary"]
  35. ----
  36. <http>
  37. <!-- ... -->
  38. <headers>
  39. <frame-options policy="SAMEORIGIN" />
  40. </headers>
  41. </http>
  42. ----
  43. .Kotlin
  44. [source,kotlin,role="secondary"]
  45. ----
  46. @Configuration
  47. @EnableWebSecurity
  48. class SecurityConfig {
  49. @Bean
  50. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  51. http {
  52. // ...
  53. headers {
  54. frameOptions {
  55. sameOrigin = true
  56. }
  57. }
  58. }
  59. return http.build()
  60. }
  61. }
  62. ----
  63. ====
  64. If you do not want the defaults to be added and want explicit control over what should be used, you can disable the defaults.
  65. The next code listing shows how to do so.
  66. If you use Spring Security's configuration, the following adds only xref:features/exploits/headers.adoc#headers-cache-control[Cache Control]:
  67. .Customize Cache Control Headers
  68. ====
  69. .Java
  70. [source,java,role="primary"]
  71. ----
  72. @Configuration
  73. @EnableWebSecurity
  74. public class WebSecurityConfig {
  75. @Bean
  76. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  77. http
  78. // ...
  79. .headers(headers -> headers
  80. // do not use any default headers unless explicitly listed
  81. .defaultsDisabled()
  82. .cacheControl(withDefaults())
  83. );
  84. return http.build();
  85. }
  86. }
  87. ----
  88. .XML
  89. [source,xml,role="secondary"]
  90. ----
  91. <http>
  92. <!-- ... -->
  93. <headers defaults-disabled="true">
  94. <cache-control/>
  95. </headers>
  96. </http>
  97. ----
  98. .Kotlin
  99. [source,kotlin,role="secondary"]
  100. ----
  101. @Configuration
  102. @EnableWebSecurity
  103. class SecurityConfig {
  104. @Bean
  105. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  106. http {
  107. // ...
  108. headers {
  109. // do not use any default headers unless explicitly listed
  110. defaultsDisabled = true
  111. cacheControl {
  112. }
  113. }
  114. }
  115. return http.build()
  116. }
  117. }
  118. ----
  119. ====
  120. If necessary, you can disable all of the HTTP Security response headers with the following configuration:
  121. .Disable All HTTP Security Headers
  122. ====
  123. .Java
  124. [source,java,role="primary"]
  125. ----
  126. @Configuration
  127. @EnableWebSecurity
  128. public class WebSecurityConfig {
  129. @Bean
  130. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  131. http
  132. // ...
  133. .headers(headers -> headers.disable());
  134. return http.build();
  135. }
  136. }
  137. ----
  138. .XML
  139. [source,xml,role="secondary"]
  140. ----
  141. <http>
  142. <!-- ... -->
  143. <headers disabled="true" />
  144. </http>
  145. ----
  146. .Kotlin
  147. [source,kotlin,role="secondary"]
  148. ----
  149. @Configuration
  150. @EnableWebSecurity
  151. class SecurityConfig {
  152. @Bean
  153. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  154. http {
  155. // ...
  156. headers {
  157. disable()
  158. }
  159. }
  160. return http.build()
  161. }
  162. }
  163. ----
  164. ====
  165. [[servlet-headers-cache-control]]
  166. == Cache Control
  167. Spring Security includes xref:features/exploits/headers.adoc#headers-cache-control[Cache Control] headers by default.
  168. 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.
  169. You can use this to ensure that content (such as CSS, JavaScript, and images) is properly cached.
  170. When you use Spring Web MVC, this is typically done within your configuration.
  171. You can find details on how to do this 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
  172. If necessary, you can also disable Spring Security's cache control HTTP response headers.
  173. .Cache Control Disabled
  174. ====
  175. .Java
  176. [source,java,role="primary"]
  177. ----
  178. @Configuration
  179. @EnableWebSecurity
  180. public class WebSecurityConfig {
  181. @Bean
  182. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  183. http
  184. // ...
  185. .headers(headers -> headers
  186. .cacheControl(cache -> cache.disable())
  187. );
  188. return http.build();
  189. }
  190. }
  191. ----
  192. .XML
  193. [source,xml,role="secondary"]
  194. ----
  195. <http>
  196. <!-- ... -->
  197. <headers>
  198. <cache-control disabled="true"/>
  199. </headers>
  200. </http>
  201. ----
  202. .Kotlin
  203. [source,kotlin,role="secondary"]
  204. ----
  205. @Configuration
  206. @EnableWebSecurity
  207. class SecurityConfig {
  208. @Bean
  209. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  210. http {
  211. headers {
  212. cacheControl {
  213. disable()
  214. }
  215. }
  216. }
  217. return http.build()
  218. }
  219. }
  220. ----
  221. ====
  222. [[servlet-headers-content-type-options]]
  223. == Content Type Options
  224. Spring Security includes xref:features/exploits/headers.adoc#headers-content-type-options[Content-Type] headers by default.
  225. However, you can disable it:
  226. .Content Type Options Disabled
  227. ====
  228. .Java
  229. [source,java,role="primary"]
  230. ----
  231. @Configuration
  232. @EnableWebSecurity
  233. public class WebSecurityConfig {
  234. @Bean
  235. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  236. http
  237. // ...
  238. .headers(headers -> headers
  239. .contentTypeOptions(contentTypeOptions -> contentTypeOptions.disable())
  240. );
  241. return http.build();
  242. }
  243. }
  244. ----
  245. .XML
  246. [source,xml,role="secondary"]
  247. ----
  248. <http>
  249. <!-- ... -->
  250. <headers>
  251. <content-type-options disabled="true"/>
  252. </headers>
  253. </http>
  254. ----
  255. .Kotlin
  256. [source,kotlin,role="secondary"]
  257. ----
  258. @Configuration
  259. @EnableWebSecurity
  260. class SecurityConfig {
  261. @Bean
  262. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  263. http {
  264. headers {
  265. contentTypeOptions {
  266. disable()
  267. }
  268. }
  269. }
  270. return http.build()
  271. }
  272. }
  273. ----
  274. ====
  275. [[servlet-headers-hsts]]
  276. == HTTP Strict Transport Security (HSTS)
  277. By default, Spring Security provides the xref:features/exploits/headers.adoc#headers-hsts[Strict Transport Security] header.
  278. However, you can explicitly customize the results.
  279. The following example explicitly provides HSTS:
  280. .Strict Transport Security
  281. ====
  282. .Java
  283. [source,java,role="primary"]
  284. ----
  285. @Configuration
  286. @EnableWebSecurity
  287. public class WebSecurityConfig {
  288. @Bean
  289. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  290. http
  291. // ...
  292. .headers(headers -> headers
  293. .httpStrictTransportSecurity(hsts -> hsts
  294. .includeSubDomains(true)
  295. .preload(true)
  296. .maxAgeInSeconds(31536000)
  297. )
  298. );
  299. return http.build();
  300. }
  301. }
  302. ----
  303. .XML
  304. [source,xml,role="secondary"]
  305. ----
  306. <http>
  307. <!-- ... -->
  308. <headers>
  309. <hsts
  310. include-subdomains="true"
  311. max-age-seconds="31536000"
  312. preload="true" />
  313. </headers>
  314. </http>
  315. ----
  316. .Kotlin
  317. [source,kotlin,role="secondary"]
  318. ----
  319. @Configuration
  320. @EnableWebSecurity
  321. class SecurityConfig {
  322. @Bean
  323. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  324. http {
  325. headers {
  326. httpStrictTransportSecurity {
  327. includeSubDomains = true
  328. preload = true
  329. maxAgeInSeconds = 31536000
  330. }
  331. }
  332. }
  333. return http.build()
  334. }
  335. }
  336. ----
  337. ====
  338. [[servlet-headers-hpkp]]
  339. == HTTP Public Key Pinning (HPKP)
  340. 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].
  341. You can enable HPKP headers with the following configuration:
  342. .HTTP Public Key Pinning
  343. ====
  344. .Java
  345. [source,java,role="primary"]
  346. ----
  347. @Configuration
  348. @EnableWebSecurity
  349. public class WebSecurityConfig {
  350. @Bean
  351. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  352. http
  353. // ...
  354. .headers(headers -> headers
  355. .httpPublicKeyPinning(hpkp -> hpkp
  356. .includeSubDomains(true)
  357. .reportUri("https://example.net/pkp-report")
  358. .addSha256Pins("d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=", "E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=")
  359. )
  360. );
  361. return http.build();
  362. }
  363. }
  364. ----
  365. .XML
  366. [source,xml,role="secondary"]
  367. ----
  368. <http>
  369. <!-- ... -->
  370. <headers>
  371. <hpkp
  372. include-subdomains="true"
  373. report-uri="https://example.net/pkp-report">
  374. <pins>
  375. <pin algorithm="sha256">d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=</pin>
  376. <pin algorithm="sha256">E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=</pin>
  377. </pins>
  378. </hpkp>
  379. </headers>
  380. </http>
  381. ----
  382. .Kotlin
  383. [source,kotlin,role="secondary"]
  384. ----
  385. @Configuration
  386. @EnableWebSecurity
  387. class SecurityConfig {
  388. @Bean
  389. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  390. http {
  391. headers {
  392. httpPublicKeyPinning {
  393. includeSubDomains = true
  394. reportUri = "https://example.net/pkp-report"
  395. pins = mapOf("d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=" to "sha256",
  396. "E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=" to "sha256")
  397. }
  398. }
  399. }
  400. return http.build()
  401. }
  402. }
  403. ----
  404. ====
  405. [[servlet-headers-frame-options]]
  406. == X-Frame-Options
  407. By default, Spring Security instructs browsers to block reflected XSS attacks by using the xref:features/exploits/headers.adoc#headers-frame-options[X-Frame-Options].
  408. For example, the following configuration specifies that Spring Security should no longer instruct browsers to block the content:
  409. .X-Frame-Options: SAMEORIGIN
  410. ====
  411. .Java
  412. [source,java,role="primary"]
  413. ----
  414. @Configuration
  415. @EnableWebSecurity
  416. public class WebSecurityConfig {
  417. @Bean
  418. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  419. http
  420. // ...
  421. .headers(headers -> headers
  422. .frameOptions(frameOptions -> frameOptions
  423. .sameOrigin()
  424. )
  425. );
  426. return http.build();
  427. }
  428. }
  429. ----
  430. .XML
  431. [source,xml,role="secondary"]
  432. ----
  433. <http>
  434. <!-- ... -->
  435. <headers>
  436. <frame-options
  437. policy="SAMEORIGIN" />
  438. </headers>
  439. </http>
  440. ----
  441. .Kotlin
  442. [source,kotlin,role="secondary"]
  443. ----
  444. @Configuration
  445. @EnableWebSecurity
  446. class SecurityConfig {
  447. @Bean
  448. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  449. http {
  450. headers {
  451. frameOptions {
  452. sameOrigin = true
  453. }
  454. }
  455. }
  456. return http.build()
  457. }
  458. }
  459. ----
  460. ====
  461. [[servlet-headers-xss-protection]]
  462. == X-XSS-Protection
  463. By default, Spring Security instructs browsers to block reflected XSS attacks by using the <<headers-xss-protection,X-XSS-Protection header>.
  464. However, you can change this default.
  465. For example, the following configuration specifies that Spring Security should no longer instruct browsers to block the content:
  466. .X-XSS-Protection Customization
  467. ====
  468. .Java
  469. [source,java,role="primary"]
  470. ----
  471. @Configuration
  472. @EnableWebSecurity
  473. public class WebSecurityConfig {
  474. @Bean
  475. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  476. http
  477. // ...
  478. .headers(headers -> headers
  479. .xssProtection(xss -> xss
  480. .block(false)
  481. )
  482. );
  483. return http.build();
  484. }
  485. }
  486. ----
  487. .XML
  488. [source,xml,role="secondary"]
  489. ----
  490. <http>
  491. <!-- ... -->
  492. <headers>
  493. <xss-protection block="false"/>
  494. </headers>
  495. </http>
  496. ----
  497. .Kotlin
  498. [source,kotlin,role="secondary"]
  499. ----
  500. @Configuration
  501. @EnableWebSecurity
  502. class SecurityConfig {
  503. @Bean
  504. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  505. // ...
  506. http {
  507. headers {
  508. xssProtection {
  509. block = false
  510. }
  511. }
  512. }
  513. return http.build()
  514. }
  515. }
  516. ----
  517. ====
  518. [[servlet-headers-csp]]
  519. == Content Security Policy (CSP)
  520. 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 knowing the context of the application.
  521. The web application author must declare the security policy (or policies) to enforce or monitor for the protected resources.
  522. Consider the following security policy:
  523. .Content Security Policy Example
  524. ====
  525. [source,http]
  526. ----
  527. Content-Security-Policy: script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/
  528. ----
  529. ====
  530. Given the preceding security policy, you can enable the CSP header:
  531. .Content Security Policy
  532. ====
  533. .Java
  534. [source,java,role="primary"]
  535. ----
  536. @Configuration
  537. @EnableWebSecurity
  538. public class WebSecurityConfig {
  539. @Bean
  540. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  541. http
  542. // ...
  543. .headers(headers -> headers
  544. .contentSecurityPolicy(csp -> csp
  545. .policyDirectives("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/")
  546. )
  547. );
  548. return http.build();
  549. }
  550. }
  551. ----
  552. .XML
  553. [source,xml,role="secondary"]
  554. ----
  555. <http>
  556. <!-- ... -->
  557. <headers>
  558. <content-security-policy
  559. policy-directives="script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/" />
  560. </headers>
  561. </http>
  562. ----
  563. .Kotlin
  564. [source,kotlin,role="secondary"]
  565. ----
  566. @Configuration
  567. @EnableWebSecurity
  568. class SecurityConfig {
  569. @Bean
  570. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  571. http {
  572. // ...
  573. headers {
  574. contentSecurityPolicy {
  575. policyDirectives = "script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/"
  576. }
  577. }
  578. }
  579. return http.build()
  580. }
  581. }
  582. ----
  583. ====
  584. To enable the CSP `report-only` header, provide the following configuration:
  585. .Content Security Policy Report Only
  586. ====
  587. .Java
  588. [source,java,role="primary"]
  589. ----
  590. @Configuration
  591. @EnableWebSecurity
  592. public class WebSecurityConfig {
  593. @Bean
  594. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  595. http
  596. // ...
  597. .headers(headers -> headers
  598. .contentSecurityPolicy(csp -> csp
  599. .policyDirectives("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/")
  600. .reportOnly()
  601. )
  602. );
  603. return http.build();
  604. }
  605. }
  606. ----
  607. .XML
  608. [source,xml,role="secondary"]
  609. ----
  610. <http>
  611. <!-- ... -->
  612. <headers>
  613. <content-security-policy
  614. policy-directives="script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/"
  615. report-only="true" />
  616. </headers>
  617. </http>
  618. ----
  619. .Kotlin
  620. [source,kotlin,role="secondary"]
  621. ----
  622. @Configuration
  623. @EnableWebSecurity
  624. class SecurityConfig {
  625. @Bean
  626. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  627. http {
  628. // ...
  629. headers {
  630. contentSecurityPolicy {
  631. policyDirectives = "script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/"
  632. reportOnly = true
  633. }
  634. }
  635. }
  636. return http.build()
  637. }
  638. }
  639. ----
  640. ====
  641. [[servlet-headers-referrer]]
  642. == Referrer Policy
  643. Spring Security does not add xref:features/exploits/headers.adoc#headers-referrer[Referrer Policy] headers by default.
  644. You can enable the Referrer Policy header by using the configuration:
  645. .Referrer Policy
  646. ====
  647. .Java
  648. [source,java,role="primary"]
  649. ----
  650. @Configuration
  651. @EnableWebSecurity
  652. public class WebSecurityConfig {
  653. @Bean
  654. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  655. http
  656. // ...
  657. .headers(headers -> headers
  658. .referrerPolicy(referrer -> referrer
  659. .policy(ReferrerPolicy.SAME_ORIGIN)
  660. )
  661. );
  662. return http.build();
  663. }
  664. }
  665. ----
  666. .XML
  667. [source,xml,role="secondary"]
  668. ----
  669. <http>
  670. <!-- ... -->
  671. <headers>
  672. <referrer-policy policy="same-origin" />
  673. </headers>
  674. </http>
  675. ----
  676. .Kotlin
  677. [source,kotlin,role="secondary"]
  678. ----
  679. @Configuration
  680. @EnableWebSecurity
  681. class SecurityConfig {
  682. @Bean
  683. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  684. http {
  685. // ...
  686. headers {
  687. referrerPolicy {
  688. policy = ReferrerPolicy.SAME_ORIGIN
  689. }
  690. }
  691. }
  692. return http.build()
  693. }
  694. }
  695. ----
  696. ====
  697. [[servlet-headers-feature]]
  698. == Feature Policy
  699. Spring Security does not add xref:features/exploits/headers.adoc#headers-feature[Feature Policy] headers by default.
  700. Consider the following `Feature-Policy` header:
  701. .Feature-Policy Example
  702. ====
  703. [source]
  704. ----
  705. Feature-Policy: geolocation 'self'
  706. ----
  707. ====
  708. You can enable the preceding feature policy header by using the following configuration:
  709. .Feature-Policy
  710. ====
  711. .Java
  712. [source,java,role="primary"]
  713. ----
  714. @Configuration
  715. @EnableWebSecurity
  716. public class WebSecurityConfig {
  717. @Bean
  718. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  719. http
  720. // ...
  721. .headers(headers -> headers
  722. .featurePolicy("geolocation 'self'")
  723. );
  724. return http.build();
  725. }
  726. }
  727. ----
  728. .XML
  729. [source,xml,role="secondary"]
  730. ----
  731. <http>
  732. <!-- ... -->
  733. <headers>
  734. <feature-policy policy-directives="geolocation 'self'" />
  735. </headers>
  736. </http>
  737. ----
  738. .Kotlin
  739. [source,kotlin,role="secondary"]
  740. ----
  741. @Configuration
  742. @EnableWebSecurity
  743. class SecurityConfig {
  744. @Bean
  745. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  746. http {
  747. // ...
  748. headers {
  749. featurePolicy("geolocation 'self'")
  750. }
  751. }
  752. return http.build()
  753. }
  754. }
  755. ----
  756. ====
  757. [[servlet-headers-permissions]]
  758. == Permissions Policy
  759. Spring Security does not add xref:features/exploits/headers.adoc#headers-permissions[Permissions Policy] headers by default.
  760. Consider the following `Permissions-Policy` header:
  761. .Permissions-Policy Example
  762. ====
  763. [source]
  764. ----
  765. Permissions-Policy: geolocation=(self)
  766. ----
  767. ====
  768. You can enable the preceding permissions policy header using the following configuration:
  769. .Permissions-Policy
  770. ====
  771. .Java
  772. [source,java,role="primary"]
  773. ----
  774. @Configuration
  775. @EnableWebSecurity
  776. public class WebSecurityConfig {
  777. @Bean
  778. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  779. http
  780. // ...
  781. .headers(headers -> headers
  782. .permissionsPolicy(permissions -> permissions
  783. .policy("geolocation=(self)")
  784. )
  785. );
  786. return http.build();
  787. }
  788. }
  789. ----
  790. .XML
  791. [source,xml,role="secondary"]
  792. ----
  793. <http>
  794. <!-- ... -->
  795. <headers>
  796. <permissions-policy policy="geolocation=(self)" />
  797. </headers>
  798. </http>
  799. ----
  800. .Kotlin
  801. [source,kotlin,role="secondary"]
  802. ----
  803. @Configuration
  804. @EnableWebSecurity
  805. class SecurityConfig {
  806. @Bean
  807. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  808. http {
  809. // ...
  810. headers {
  811. permissionPolicy {
  812. policy = "geolocation=(self)"
  813. }
  814. }
  815. }
  816. return http.build()
  817. }
  818. }
  819. ----
  820. ====
  821. [[servlet-headers-clear-site-data]]
  822. == Clear Site Data
  823. Spring Security does not add xref:features/exploits/headers.adoc#headers-clear-site-data[Clear-Site-Data] headers by default.
  824. Consider the following Clear-Site-Data header:
  825. .Clear-Site-Data Example
  826. ====
  827. ----
  828. Clear-Site-Data: "cache", "cookies"
  829. ----
  830. ====
  831. You can send the preceding header on log out with the following configuration:
  832. .Clear-Site-Data
  833. ====
  834. .Java
  835. [source,java,role="primary"]
  836. ----
  837. @Configuration
  838. @EnableWebSecurity
  839. public class WebSecurityConfig {
  840. @Bean
  841. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  842. http
  843. // ...
  844. .logout((logout) -> logout
  845. .addLogoutHandler(new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(CACHE, COOKIES)))
  846. );
  847. return http.build();
  848. }
  849. }
  850. ----
  851. .Kotlin
  852. [source,kotlin,role="secondary"]
  853. ----
  854. @Configuration
  855. @EnableWebSecurity
  856. class SecurityConfig {
  857. @Bean
  858. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  859. http {
  860. // ...
  861. logout {
  862. addLogoutHandler(HeaderWriterLogoutHandler(ClearSiteDataHeaderWriter(CACHE, COOKIES)))
  863. }
  864. }
  865. return http.build()
  866. }
  867. }
  868. ----
  869. ====
  870. [[servlet-headers-custom]]
  871. == Custom Headers
  872. Spring Security has mechanisms to make it convenient to add the more common security headers to your application.
  873. However, it also provides hooks to enable adding custom headers.
  874. [[servlet-headers-static]]
  875. === Static Headers
  876. There may be times when you wish to inject custom security headers that are not supported out of the box into your application.
  877. Consider the following custom security header:
  878. [source]
  879. ----
  880. X-Custom-Security-Header: header-value
  881. ----
  882. Given the preceding header, you could add the headers to the response by using the following configuration:
  883. .StaticHeadersWriter
  884. ====
  885. .Java
  886. [source,java,role="primary"]
  887. ----
  888. @Configuration
  889. @EnableWebSecurity
  890. public class WebSecurityConfig {
  891. @Bean
  892. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  893. http
  894. // ...
  895. .headers(headers -> headers
  896. .addHeaderWriter(new StaticHeadersWriter("X-Custom-Security-Header","header-value"))
  897. );
  898. return http.build();
  899. }
  900. }
  901. ----
  902. .XML
  903. [source,xml,role="secondary"]
  904. ----
  905. <http>
  906. <!-- ... -->
  907. <headers>
  908. <header name="X-Custom-Security-Header" value="header-value"/>
  909. </headers>
  910. </http>
  911. ----
  912. .Kotlin
  913. [source,kotlin,role="secondary"]
  914. ----
  915. @Configuration
  916. @EnableWebSecurity
  917. class SecurityConfig {
  918. @Bean
  919. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  920. http {
  921. // ...
  922. headers {
  923. addHeaderWriter(StaticHeadersWriter("X-Custom-Security-Header","header-value"))
  924. }
  925. }
  926. return http.build()
  927. }
  928. }
  929. ----
  930. ====
  931. [[servlet-headers-writer]]
  932. === Headers Writer
  933. 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`.
  934. The next example use a custom instance of `XFrameOptionsHeaderWriter`.
  935. If you wanted to explicitly configure <<servlet-headers-frame-options>>, you could do so with the following configuration:
  936. .Headers Writer
  937. ====
  938. .Java
  939. [source,java,role="primary"]
  940. ----
  941. @Configuration
  942. @EnableWebSecurity
  943. public class WebSecurityConfig {
  944. @Bean
  945. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  946. http
  947. // ...
  948. .headers(headers -> headers
  949. .addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN))
  950. );
  951. return http.build();
  952. }
  953. }
  954. ----
  955. .XML
  956. [source,xml,role="secondary"]
  957. ----
  958. <http>
  959. <!-- ... -->
  960. <headers>
  961. <header ref="frameOptionsWriter"/>
  962. </headers>
  963. </http>
  964. <!-- Requires the c-namespace.
  965. See https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-c-namespace
  966. -->
  967. <beans:bean id="frameOptionsWriter"
  968. class="org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter"
  969. c:frameOptionsMode="SAMEORIGIN"/>
  970. ----
  971. .Kotlin
  972. [source,kotlin,role="secondary"]
  973. ----
  974. @Configuration
  975. @EnableWebSecurity
  976. class SecurityConfig {
  977. @Bean
  978. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  979. http {
  980. // ...
  981. headers {
  982. addHeaderWriter(XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN))
  983. }
  984. }
  985. return http.build()
  986. }
  987. }
  988. ----
  989. ====
  990. [[headers-delegatingrequestmatcherheaderwriter]]
  991. === DelegatingRequestMatcherHeaderWriter
  992. At times, you may want to write a header only for certain requests.
  993. For example, perhaps you want to protect only your login page from being framed.
  994. You could use the `DelegatingRequestMatcherHeaderWriter` to do so.
  995. The following configuration example uses `DelegatingRequestMatcherHeaderWriter`:
  996. .DelegatingRequestMatcherHeaderWriter Java Configuration
  997. ====
  998. .Java
  999. [source,java,role="primary"]
  1000. ----
  1001. @Configuration
  1002. @EnableWebSecurity
  1003. public class WebSecurityConfig {
  1004. @Bean
  1005. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  1006. RequestMatcher matcher = new AntPathRequestMatcher("/login");
  1007. DelegatingRequestMatcherHeaderWriter headerWriter =
  1008. new DelegatingRequestMatcherHeaderWriter(matcher,new XFrameOptionsHeaderWriter());
  1009. http
  1010. // ...
  1011. .headers(headers -> headers
  1012. .frameOptions(frameOptions -> frameOptions.disable())
  1013. .addHeaderWriter(headerWriter)
  1014. );
  1015. return http.build();
  1016. }
  1017. }
  1018. ----
  1019. .XML
  1020. [source,xml,role="secondary"]
  1021. ----
  1022. <http>
  1023. <!-- ... -->
  1024. <headers>
  1025. <frame-options disabled="true"/>
  1026. <header ref="headerWriter"/>
  1027. </headers>
  1028. </http>
  1029. <beans:bean id="headerWriter"
  1030. class="org.springframework.security.web.header.writers.DelegatingRequestMatcherHeaderWriter">
  1031. <beans:constructor-arg>
  1032. <bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher"
  1033. c:pattern="/login"/>
  1034. </beans:constructor-arg>
  1035. <beans:constructor-arg>
  1036. <beans:bean
  1037. class="org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter"/>
  1038. </beans:constructor-arg>
  1039. </beans:bean>
  1040. ----
  1041. .Kotlin
  1042. [source,kotlin,role="secondary"]
  1043. ----
  1044. @Configuration
  1045. @EnableWebSecurity
  1046. class SecurityConfig {
  1047. @Bean
  1048. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  1049. val matcher: RequestMatcher = AntPathRequestMatcher("/login")
  1050. val headerWriter = DelegatingRequestMatcherHeaderWriter(matcher, XFrameOptionsHeaderWriter())
  1051. http {
  1052. headers {
  1053. frameOptions {
  1054. disable()
  1055. }
  1056. addHeaderWriter(headerWriter)
  1057. }
  1058. }
  1059. return http.build()
  1060. }
  1061. }
  1062. ----
  1063. ====