headers.adoc 26 KB

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