headers.adoc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221
  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 disable the XSS Auditor by using <<headers-xss-protection,X-XSS-Protection header>.
  464. However, you can change this default.
  465. For example, the following configuration specifies that Spring Security instruct compatible browsers to enable filtering,
  466. and block the content:
  467. .X-XSS-Protection Customization
  468. ====
  469. .Java
  470. [source,java,role="primary"]
  471. ----
  472. @Configuration
  473. @EnableWebSecurity
  474. public class WebSecurityConfig {
  475. @Bean
  476. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  477. http
  478. // ...
  479. .headers(headers -> headers
  480. .xssProtection(xss -> xss
  481. .headerValue(XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK)
  482. )
  483. );
  484. return http.build();
  485. }
  486. }
  487. ----
  488. .XML
  489. [source,xml,role="secondary"]
  490. ----
  491. <http>
  492. <!-- ... -->
  493. <headers>
  494. <xss-protection headerValue="1; mode=block"/>
  495. </headers>
  496. </http>
  497. ----
  498. .Kotlin
  499. [source,kotlin,role="secondary"]
  500. ----
  501. @Configuration
  502. @EnableWebSecurity
  503. class SecurityConfig {
  504. @Bean
  505. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  506. // ...
  507. http {
  508. headers {
  509. xssProtection {
  510. headerValue = XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK
  511. }
  512. }
  513. }
  514. return http.build()
  515. }
  516. }
  517. ----
  518. ====
  519. [[servlet-headers-csp]]
  520. == Content Security Policy (CSP)
  521. 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.
  522. The web application author must declare the security policy (or policies) to enforce or monitor for the protected resources.
  523. Consider the following security policy:
  524. .Content Security Policy Example
  525. ====
  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. ====
  531. Given the preceding security policy, you can enable the CSP header:
  532. .Content Security Policy
  533. ====
  534. .Java
  535. [source,java,role="primary"]
  536. ----
  537. @Configuration
  538. @EnableWebSecurity
  539. public class WebSecurityConfig {
  540. @Bean
  541. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  542. http
  543. // ...
  544. .headers(headers -> headers
  545. .contentSecurityPolicy(csp -> csp
  546. .policyDirectives("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/")
  547. )
  548. );
  549. return http.build();
  550. }
  551. }
  552. ----
  553. .XML
  554. [source,xml,role="secondary"]
  555. ----
  556. <http>
  557. <!-- ... -->
  558. <headers>
  559. <content-security-policy
  560. policy-directives="script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/" />
  561. </headers>
  562. </http>
  563. ----
  564. .Kotlin
  565. [source,kotlin,role="secondary"]
  566. ----
  567. @Configuration
  568. @EnableWebSecurity
  569. class SecurityConfig {
  570. @Bean
  571. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  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. return http.build()
  581. }
  582. }
  583. ----
  584. ====
  585. To enable the CSP `report-only` header, provide the following configuration:
  586. .Content Security Policy Report Only
  587. ====
  588. .Java
  589. [source,java,role="primary"]
  590. ----
  591. @Configuration
  592. @EnableWebSecurity
  593. public class WebSecurityConfig {
  594. @Bean
  595. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  596. http
  597. // ...
  598. .headers(headers -> headers
  599. .contentSecurityPolicy(csp -> csp
  600. .policyDirectives("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/")
  601. .reportOnly()
  602. )
  603. );
  604. return http.build();
  605. }
  606. }
  607. ----
  608. .XML
  609. [source,xml,role="secondary"]
  610. ----
  611. <http>
  612. <!-- ... -->
  613. <headers>
  614. <content-security-policy
  615. policy-directives="script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/"
  616. report-only="true" />
  617. </headers>
  618. </http>
  619. ----
  620. .Kotlin
  621. [source,kotlin,role="secondary"]
  622. ----
  623. @Configuration
  624. @EnableWebSecurity
  625. class SecurityConfig {
  626. @Bean
  627. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  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. return http.build()
  638. }
  639. }
  640. ----
  641. ====
  642. [[servlet-headers-referrer]]
  643. == Referrer Policy
  644. Spring Security does not add xref:features/exploits/headers.adoc#headers-referrer[Referrer Policy] headers by default.
  645. You can enable the Referrer Policy header by using the configuration:
  646. .Referrer Policy
  647. ====
  648. .Java
  649. [source,java,role="primary"]
  650. ----
  651. @Configuration
  652. @EnableWebSecurity
  653. public class WebSecurityConfig {
  654. @Bean
  655. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  656. http
  657. // ...
  658. .headers(headers -> headers
  659. .referrerPolicy(referrer -> referrer
  660. .policy(ReferrerPolicy.SAME_ORIGIN)
  661. )
  662. );
  663. return http.build();
  664. }
  665. }
  666. ----
  667. .XML
  668. [source,xml,role="secondary"]
  669. ----
  670. <http>
  671. <!-- ... -->
  672. <headers>
  673. <referrer-policy policy="same-origin" />
  674. </headers>
  675. </http>
  676. ----
  677. .Kotlin
  678. [source,kotlin,role="secondary"]
  679. ----
  680. @Configuration
  681. @EnableWebSecurity
  682. class SecurityConfig {
  683. @Bean
  684. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  685. http {
  686. // ...
  687. headers {
  688. referrerPolicy {
  689. policy = ReferrerPolicy.SAME_ORIGIN
  690. }
  691. }
  692. }
  693. return http.build()
  694. }
  695. }
  696. ----
  697. ====
  698. [[servlet-headers-feature]]
  699. == Feature Policy
  700. Spring Security does not add xref:features/exploits/headers.adoc#headers-feature[Feature Policy] headers by default.
  701. Consider the following `Feature-Policy` header:
  702. .Feature-Policy Example
  703. ====
  704. [source]
  705. ----
  706. Feature-Policy: geolocation 'self'
  707. ----
  708. ====
  709. You can enable the preceding feature policy header by using the following configuration:
  710. .Feature-Policy
  711. ====
  712. .Java
  713. [source,java,role="primary"]
  714. ----
  715. @Configuration
  716. @EnableWebSecurity
  717. public class WebSecurityConfig {
  718. @Bean
  719. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  720. http
  721. // ...
  722. .headers(headers -> headers
  723. .featurePolicy("geolocation 'self'")
  724. );
  725. return http.build();
  726. }
  727. }
  728. ----
  729. .XML
  730. [source,xml,role="secondary"]
  731. ----
  732. <http>
  733. <!-- ... -->
  734. <headers>
  735. <feature-policy policy-directives="geolocation 'self'" />
  736. </headers>
  737. </http>
  738. ----
  739. .Kotlin
  740. [source,kotlin,role="secondary"]
  741. ----
  742. @Configuration
  743. @EnableWebSecurity
  744. class SecurityConfig {
  745. @Bean
  746. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  747. http {
  748. // ...
  749. headers {
  750. featurePolicy("geolocation 'self'")
  751. }
  752. }
  753. return http.build()
  754. }
  755. }
  756. ----
  757. ====
  758. [[servlet-headers-permissions]]
  759. == Permissions Policy
  760. Spring Security does not add xref:features/exploits/headers.adoc#headers-permissions[Permissions Policy] headers by default.
  761. Consider the following `Permissions-Policy` header:
  762. .Permissions-Policy Example
  763. ====
  764. [source]
  765. ----
  766. Permissions-Policy: geolocation=(self)
  767. ----
  768. ====
  769. You can enable the preceding permissions policy header using the following configuration:
  770. .Permissions-Policy
  771. ====
  772. .Java
  773. [source,java,role="primary"]
  774. ----
  775. @Configuration
  776. @EnableWebSecurity
  777. public class WebSecurityConfig {
  778. @Bean
  779. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  780. http
  781. // ...
  782. .headers(headers -> headers
  783. .permissionsPolicy(permissions -> permissions
  784. .policy("geolocation=(self)")
  785. )
  786. );
  787. return http.build();
  788. }
  789. }
  790. ----
  791. .XML
  792. [source,xml,role="secondary"]
  793. ----
  794. <http>
  795. <!-- ... -->
  796. <headers>
  797. <permissions-policy policy="geolocation=(self)" />
  798. </headers>
  799. </http>
  800. ----
  801. .Kotlin
  802. [source,kotlin,role="secondary"]
  803. ----
  804. @Configuration
  805. @EnableWebSecurity
  806. class SecurityConfig {
  807. @Bean
  808. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  809. http {
  810. // ...
  811. headers {
  812. permissionPolicy {
  813. policy = "geolocation=(self)"
  814. }
  815. }
  816. }
  817. return http.build()
  818. }
  819. }
  820. ----
  821. ====
  822. [[servlet-headers-clear-site-data]]
  823. == Clear Site Data
  824. Spring Security does not add xref:features/exploits/headers.adoc#headers-clear-site-data[Clear-Site-Data] headers by default.
  825. Consider the following Clear-Site-Data header:
  826. .Clear-Site-Data Example
  827. ====
  828. ----
  829. Clear-Site-Data: "cache", "cookies"
  830. ----
  831. ====
  832. You can send the preceding header on log out with the following configuration:
  833. .Clear-Site-Data
  834. ====
  835. .Java
  836. [source,java,role="primary"]
  837. ----
  838. @Configuration
  839. @EnableWebSecurity
  840. public class WebSecurityConfig {
  841. @Bean
  842. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  843. http
  844. // ...
  845. .logout((logout) -> logout
  846. .addLogoutHandler(new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(CACHE, COOKIES)))
  847. );
  848. return http.build();
  849. }
  850. }
  851. ----
  852. .Kotlin
  853. [source,kotlin,role="secondary"]
  854. ----
  855. @Configuration
  856. @EnableWebSecurity
  857. class SecurityConfig {
  858. @Bean
  859. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  860. http {
  861. // ...
  862. logout {
  863. addLogoutHandler(HeaderWriterLogoutHandler(ClearSiteDataHeaderWriter(CACHE, COOKIES)))
  864. }
  865. }
  866. return http.build()
  867. }
  868. }
  869. ----
  870. ====
  871. [[servlet-headers-custom]]
  872. == Custom Headers
  873. Spring Security has mechanisms to make it convenient to add the more common security headers to your application.
  874. However, it also provides hooks to enable adding custom headers.
  875. [[servlet-headers-static]]
  876. === Static Headers
  877. There may be times when you wish to inject custom security headers that are not supported out of the box into your application.
  878. Consider the following custom security header:
  879. [source]
  880. ----
  881. X-Custom-Security-Header: header-value
  882. ----
  883. Given the preceding header, you could add the headers to the response by using the following configuration:
  884. .StaticHeadersWriter
  885. ====
  886. .Java
  887. [source,java,role="primary"]
  888. ----
  889. @Configuration
  890. @EnableWebSecurity
  891. public class WebSecurityConfig {
  892. @Bean
  893. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  894. http
  895. // ...
  896. .headers(headers -> headers
  897. .addHeaderWriter(new StaticHeadersWriter("X-Custom-Security-Header","header-value"))
  898. );
  899. return http.build();
  900. }
  901. }
  902. ----
  903. .XML
  904. [source,xml,role="secondary"]
  905. ----
  906. <http>
  907. <!-- ... -->
  908. <headers>
  909. <header name="X-Custom-Security-Header" value="header-value"/>
  910. </headers>
  911. </http>
  912. ----
  913. .Kotlin
  914. [source,kotlin,role="secondary"]
  915. ----
  916. @Configuration
  917. @EnableWebSecurity
  918. class SecurityConfig {
  919. @Bean
  920. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  921. http {
  922. // ...
  923. headers {
  924. addHeaderWriter(StaticHeadersWriter("X-Custom-Security-Header","header-value"))
  925. }
  926. }
  927. return http.build()
  928. }
  929. }
  930. ----
  931. ====
  932. [[servlet-headers-writer]]
  933. === Headers Writer
  934. 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`.
  935. The next example use a custom instance of `XFrameOptionsHeaderWriter`.
  936. If you wanted to explicitly configure <<servlet-headers-frame-options>>, you could do so with the following configuration:
  937. .Headers Writer
  938. ====
  939. .Java
  940. [source,java,role="primary"]
  941. ----
  942. @Configuration
  943. @EnableWebSecurity
  944. public class WebSecurityConfig {
  945. @Bean
  946. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  947. http
  948. // ...
  949. .headers(headers -> headers
  950. .addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN))
  951. );
  952. return http.build();
  953. }
  954. }
  955. ----
  956. .XML
  957. [source,xml,role="secondary"]
  958. ----
  959. <http>
  960. <!-- ... -->
  961. <headers>
  962. <header ref="frameOptionsWriter"/>
  963. </headers>
  964. </http>
  965. <!-- Requires the c-namespace.
  966. See https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-c-namespace
  967. -->
  968. <beans:bean id="frameOptionsWriter"
  969. class="org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter"
  970. c:frameOptionsMode="SAMEORIGIN"/>
  971. ----
  972. .Kotlin
  973. [source,kotlin,role="secondary"]
  974. ----
  975. @Configuration
  976. @EnableWebSecurity
  977. class SecurityConfig {
  978. @Bean
  979. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  980. http {
  981. // ...
  982. headers {
  983. addHeaderWriter(XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN))
  984. }
  985. }
  986. return http.build()
  987. }
  988. }
  989. ----
  990. ====
  991. [[headers-delegatingrequestmatcherheaderwriter]]
  992. === DelegatingRequestMatcherHeaderWriter
  993. At times, you may want to write a header only for certain requests.
  994. For example, perhaps you want to protect only your login page from being framed.
  995. You could use the `DelegatingRequestMatcherHeaderWriter` to do so.
  996. The following configuration example uses `DelegatingRequestMatcherHeaderWriter`:
  997. .DelegatingRequestMatcherHeaderWriter Java Configuration
  998. ====
  999. .Java
  1000. [source,java,role="primary"]
  1001. ----
  1002. @Configuration
  1003. @EnableWebSecurity
  1004. public class WebSecurityConfig {
  1005. @Bean
  1006. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  1007. RequestMatcher matcher = new AntPathRequestMatcher("/login");
  1008. DelegatingRequestMatcherHeaderWriter headerWriter =
  1009. new DelegatingRequestMatcherHeaderWriter(matcher,new XFrameOptionsHeaderWriter());
  1010. http
  1011. // ...
  1012. .headers(headers -> headers
  1013. .frameOptions(frameOptions -> frameOptions.disable())
  1014. .addHeaderWriter(headerWriter)
  1015. );
  1016. return http.build();
  1017. }
  1018. }
  1019. ----
  1020. .XML
  1021. [source,xml,role="secondary"]
  1022. ----
  1023. <http>
  1024. <!-- ... -->
  1025. <headers>
  1026. <frame-options disabled="true"/>
  1027. <header ref="headerWriter"/>
  1028. </headers>
  1029. </http>
  1030. <beans:bean id="headerWriter"
  1031. class="org.springframework.security.web.header.writers.DelegatingRequestMatcherHeaderWriter">
  1032. <beans:constructor-arg>
  1033. <bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher"
  1034. c:pattern="/login"/>
  1035. </beans:constructor-arg>
  1036. <beans:constructor-arg>
  1037. <beans:bean
  1038. class="org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter"/>
  1039. </beans:constructor-arg>
  1040. </beans:bean>
  1041. ----
  1042. .Kotlin
  1043. [source,kotlin,role="secondary"]
  1044. ----
  1045. @Configuration
  1046. @EnableWebSecurity
  1047. class SecurityConfig {
  1048. @Bean
  1049. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  1050. val matcher: RequestMatcher = AntPathRequestMatcher("/login")
  1051. val headerWriter = DelegatingRequestMatcherHeaderWriter(matcher, XFrameOptionsHeaderWriter())
  1052. http {
  1053. headers {
  1054. frameOptions {
  1055. disable()
  1056. }
  1057. addHeaderWriter(headerWriter)
  1058. }
  1059. }
  1060. return http.build()
  1061. }
  1062. }
  1063. ----
  1064. ====