headers.adoc 26 KB

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