headers.adoc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. [[webflux-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 WebFlux-based support for Security HTTP Response Headers.
  5. [[webflux-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 xref:servlet/exploits/headers.adoc#servlet-headers-frame-options[`X-Frame-Options`].
  11. You can do so with the following configuration:
  12. .Customize Default Security Headers
  13. [tabs]
  14. ======
  15. Java::
  16. +
  17. [source,java,role="primary"]
  18. ----
  19. @Bean
  20. SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
  21. http
  22. // ...
  23. .headers((headers) -> headers
  24. .frameOptions((frameOptions) -> frameOptions
  25. .mode(Mode.SAMEORIGIN)
  26. )
  27. );
  28. return http.build();
  29. }
  30. ----
  31. Kotlin::
  32. +
  33. [source,kotlin,role="secondary"]
  34. ----
  35. @Bean
  36. fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
  37. return http {
  38. // ...
  39. headers {
  40. frameOptions {
  41. mode = Mode.SAMEORIGIN
  42. }
  43. }
  44. }
  45. }
  46. ----
  47. ======
  48. If you do not want the defaults to be added and want explicit control over what should be used, you can disable the defaults:
  49. .Disable HTTP Security Response Headers
  50. [tabs]
  51. ======
  52. Java::
  53. +
  54. [source,java,role="primary"]
  55. ----
  56. @Bean
  57. SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
  58. http
  59. // ...
  60. .headers((headers) -> headers.disable());
  61. return http.build();
  62. }
  63. ----
  64. Kotlin::
  65. +
  66. [source,kotlin,role="secondary"]
  67. ----
  68. @Bean
  69. fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
  70. return http {
  71. // ...
  72. headers {
  73. disable()
  74. }
  75. }
  76. }
  77. ----
  78. ======
  79. [[webflux-headers-cache-control]]
  80. == Cache Control
  81. Spring Security includes xref:features/exploits/headers.adoc#headers-cache-control[Cache Control] headers by default.
  82. However, if you actually want to cache specific responses, your application can selectively add them to the https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/server/reactive/ServerHttpResponse.html[`ServerHttpResponse`] to override the header set by Spring Security.
  83. This is useful to ensure that such things as CSS, JavaScript, and images are properly cached.
  84. When using Spring WebFlux, you typically do so within your configuration.
  85. You can find details on how to do so in the https://docs.spring.io/spring/docs/5.0.0.RELEASE/spring-framework-reference/web-reactive.html#webflux-config-static-resources[Static Resources] portion of the Spring Reference documentation.
  86. If necessary, you can also disable Spring Security's cache control HTTP response headers.
  87. .Cache Control Disabled
  88. [tabs]
  89. ======
  90. Java::
  91. +
  92. [source,java,role="primary"]
  93. ----
  94. @Bean
  95. SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
  96. http
  97. // ...
  98. .headers((headers) -> headers
  99. .cache((cache) -> cache.disable())
  100. );
  101. return http.build();
  102. }
  103. ----
  104. Kotlin::
  105. +
  106. [source,kotlin,role="secondary"]
  107. ----
  108. @Bean
  109. fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
  110. return http {
  111. // ...
  112. headers {
  113. cache {
  114. disable()
  115. }
  116. }
  117. }
  118. }
  119. ----
  120. ======
  121. [[webflux-headers-content-type-options]]
  122. == Content Type Options
  123. By default, Spring Security includes xref:features/exploits/headers.adoc#headers-content-type-options[Content-Type] headers.
  124. However, you can disable it:
  125. .Content Type Options Disabled
  126. [tabs]
  127. ======
  128. Java::
  129. +
  130. [source,java,role="primary"]
  131. ----
  132. @Bean
  133. SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
  134. http
  135. // ...
  136. .headers((headers) -> headers
  137. .contentTypeOptions((contentTypeOptions) -> contentTypeOptions.disable())
  138. );
  139. return http.build();
  140. }
  141. ----
  142. Kotlin::
  143. +
  144. [source,kotlin,role="secondary"]
  145. ----
  146. @Bean
  147. fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
  148. return http {
  149. // ...
  150. headers {
  151. contentTypeOptions {
  152. disable()
  153. }
  154. }
  155. }
  156. }
  157. ----
  158. ======
  159. [[webflux-headers-hsts]]
  160. == HTTP Strict Transport Security (HSTS)
  161. By default, Spring Security provides the xref:features/exploits/headers.adoc#headers-hsts[Strict Transport Security] header.
  162. However, you can customize the results explicitly.
  163. For example, the following example explicitly provides HSTS:
  164. .Strict Transport Security
  165. [tabs]
  166. ======
  167. Java::
  168. +
  169. [source,java,role="primary"]
  170. ----
  171. @Bean
  172. SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
  173. http
  174. // ...
  175. .headers((headers) -> headers
  176. .hsts((hsts) -> hsts
  177. .includeSubdomains(true)
  178. .preload(true)
  179. .maxAge(Duration.ofDays(365))
  180. )
  181. );
  182. return http.build();
  183. }
  184. ----
  185. Kotlin::
  186. +
  187. [source,kotlin,role="secondary"]
  188. ----
  189. @Bean
  190. fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
  191. return http {
  192. // ...
  193. headers {
  194. hsts {
  195. includeSubdomains = true
  196. preload = true
  197. maxAge = Duration.ofDays(365)
  198. }
  199. }
  200. }
  201. }
  202. ----
  203. ======
  204. [[webflux-headers-frame-options]]
  205. == X-Frame-Options
  206. By default, Spring Security disables rendering within an iframe by using xref:features/exploits/headers.adoc#headers-frame-options[`X-Frame-Options`].
  207. You can customize frame options to use the same origin:
  208. .X-Frame-Options: SAMEORIGIN
  209. [tabs]
  210. ======
  211. Java::
  212. +
  213. [source,java,role="primary"]
  214. ----
  215. @Bean
  216. SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
  217. http
  218. // ...
  219. .headers((headers) -> headers
  220. .frameOptions((frameOptions) -> frameOptions
  221. .mode(SAMEORIGIN)
  222. )
  223. );
  224. return http.build();
  225. }
  226. ----
  227. Kotlin::
  228. +
  229. [source,kotlin,role="secondary"]
  230. ----
  231. @Bean
  232. fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
  233. return http {
  234. // ...
  235. headers {
  236. frameOptions {
  237. mode = SAMEORIGIN
  238. }
  239. }
  240. }
  241. }
  242. ----
  243. ======
  244. [[webflux-headers-xss-protection]]
  245. == X-XSS-Protection
  246. By default, Spring Security instructs browsers to disable the XSS Auditor by using <<headers-xss-protection,X-XSS-Protection header>.
  247. You can disable the `X-XSS-Protection` header entirely:
  248. .X-XSS-Protection Customization
  249. [tabs]
  250. ======
  251. Java::
  252. +
  253. [source,java,role="primary"]
  254. ----
  255. @Bean
  256. SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
  257. http
  258. // ...
  259. .headers((headers) -> headers
  260. .xssProtection((xssProtection) -> xssProtection.disable())
  261. );
  262. return http.build();
  263. }
  264. ----
  265. Kotlin::
  266. +
  267. [source,kotlin,role="secondary"]
  268. ----
  269. @Bean
  270. fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
  271. return http {
  272. // ...
  273. headers {
  274. xssProtection {
  275. disable()
  276. }
  277. }
  278. }
  279. }
  280. ----
  281. ======
  282. You can also change the header value:
  283. .X-XSS-Protection Explicit header value
  284. [tabs]
  285. ======
  286. Java::
  287. +
  288. [source,java,role="primary"]
  289. ----
  290. @Bean
  291. SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
  292. http
  293. // ...
  294. .headers((headers) -> headers
  295. .xssProtection((xssProtection) -> xssProtection.headerValue(XXssProtectionServerHttpHeadersWriter.HeaderValue.ENABLED_MODE_BLOCK))
  296. );
  297. return http.build();
  298. }
  299. ----
  300. Kotlin::
  301. +
  302. [source,kotlin,role="secondary"]
  303. ----
  304. @Bean
  305. fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
  306. return http {
  307. // ...
  308. headers {
  309. xssProtection {
  310. headerValue = XXssProtectionServerHttpHeadersWriter.HeaderValue.ENABLED_MODE_BLOCK
  311. }
  312. }
  313. }
  314. }
  315. ----
  316. ======
  317. [[webflux-headers-csp]]
  318. == Content Security Policy (CSP)
  319. By default, Spring Security does not add xref:features/exploits/headers.adoc#headers-csp[Content Security Policy], because a reasonable default is impossible to know without the context of the application.
  320. The web application author must declare the security policies to enforce and/or monitor for the protected resources.
  321. For example, consider the following security policy:
  322. .Content Security Policy Example
  323. [source,http]
  324. ----
  325. Content-Security-Policy: script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/
  326. ----
  327. Given the preceding policy, you can enable the CSP header:
  328. .Content Security Policy
  329. [tabs]
  330. ======
  331. Java::
  332. +
  333. [source,java,role="primary"]
  334. ----
  335. @Bean
  336. SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
  337. http
  338. // ...
  339. .headers((headers) -> headers
  340. .contentSecurityPolicy((policy) -> policy
  341. .policyDirectives("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/")
  342. )
  343. );
  344. return http.build();
  345. }
  346. ----
  347. Kotlin::
  348. +
  349. [source,kotlin,role="secondary"]
  350. ----
  351. @Bean
  352. fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
  353. return http {
  354. // ...
  355. headers {
  356. contentSecurityPolicy {
  357. policyDirectives = "script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/"
  358. }
  359. }
  360. }
  361. }
  362. ----
  363. ======
  364. To enable the CSP `report-only` header, provide the following configuration:
  365. .Content Security Policy Report Only
  366. [tabs]
  367. ======
  368. Java::
  369. +
  370. [source,java,role="primary"]
  371. ----
  372. @Bean
  373. SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
  374. http
  375. // ...
  376. .headers((headers) -> headers
  377. .contentSecurityPolicy((policy) -> policy
  378. .policyDirectives("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/")
  379. .reportOnly()
  380. )
  381. );
  382. return http.build();
  383. }
  384. ----
  385. Kotlin::
  386. +
  387. [source,kotlin,role="secondary"]
  388. ----
  389. @Bean
  390. fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
  391. return http {
  392. // ...
  393. headers {
  394. contentSecurityPolicy {
  395. policyDirectives = "script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/"
  396. reportOnly = true
  397. }
  398. }
  399. }
  400. }
  401. ----
  402. ======
  403. [[webflux-headers-referrer]]
  404. == Referrer Policy
  405. Spring Security adds the xref:features/exploits/headers.adoc#headers-referrer[Referrer Policy] header by default with the directive `no-referrer`.
  406. You can change the Referrer Policy header using configuration as shown below:
  407. .Referrer Policy Configuration
  408. [tabs]
  409. ======
  410. Java::
  411. +
  412. [source,java,role="primary"]
  413. ----
  414. @Bean
  415. SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
  416. http
  417. // ...
  418. .headers((headers) -> headers
  419. .referrerPolicy((referrer) -> referrer
  420. .policy(ReferrerPolicy.SAME_ORIGIN)
  421. )
  422. );
  423. return http.build();
  424. }
  425. ----
  426. Kotlin::
  427. +
  428. [source,kotlin,role="secondary"]
  429. ----
  430. @Bean
  431. fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
  432. return http {
  433. // ...
  434. headers {
  435. referrerPolicy {
  436. policy = ReferrerPolicy.SAME_ORIGIN
  437. }
  438. }
  439. }
  440. }
  441. ----
  442. ======
  443. [[webflux-headers-feature]]
  444. == Feature Policy
  445. By default, Spring Security does not add xref:features/exploits/headers.adoc#headers-feature[Feature Policy] headers.
  446. Consider the following `Feature-Policy` header:
  447. .Feature-Policy Example
  448. [source]
  449. ----
  450. Feature-Policy: geolocation 'self'
  451. ----
  452. You can enable the preceding Feature Policy header:
  453. .Feature-Policy Configuration
  454. [tabs]
  455. ======
  456. Java::
  457. +
  458. [source,java,role="primary"]
  459. ----
  460. @Bean
  461. SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
  462. http
  463. // ...
  464. .headers((headers) -> headers
  465. .featurePolicy("geolocation 'self'")
  466. );
  467. return http.build();
  468. }
  469. ----
  470. Kotlin::
  471. +
  472. [source,kotlin,role="secondary"]
  473. ----
  474. @Bean
  475. fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
  476. return http {
  477. // ...
  478. headers {
  479. featurePolicy("geolocation 'self'")
  480. }
  481. }
  482. }
  483. ----
  484. ======
  485. [[webflux-headers-permissions]]
  486. == Permissions Policy
  487. By default, Spring Security does not add xref:features/exploits/headers.adoc#headers-permissions[Permissions Policy] headers.
  488. Consider the following `Permissions-Policy` header:
  489. .Permissions-Policy Example
  490. [source]
  491. ----
  492. Permissions-Policy: geolocation=(self)
  493. ----
  494. You can enable the preceding Permissions Policy header:
  495. .Permissions-Policy Configuration
  496. [tabs]
  497. ======
  498. Java::
  499. +
  500. [source,java,role="primary"]
  501. ----
  502. @Bean
  503. SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
  504. http
  505. // ...
  506. .headers((headers) -> headers
  507. .permissionsPolicy((permissions) -> permissions
  508. .policy("geolocation=(self)")
  509. )
  510. );
  511. return http.build();
  512. }
  513. ----
  514. Kotlin::
  515. +
  516. [source,kotlin,role="secondary"]
  517. ----
  518. @Bean
  519. fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
  520. return http {
  521. // ...
  522. headers {
  523. permissionsPolicy {
  524. policy = "geolocation=(self)"
  525. }
  526. }
  527. }
  528. }
  529. ----
  530. ======
  531. [[webflux-headers-clear-site-data]]
  532. == Clear Site Data
  533. By default, Spring Security does not add xref:features/exploits/headers.adoc#headers-clear-site-data[Clear-Site-Data] headers.
  534. Consider the following `Clear-Site-Data` header:
  535. .Clear-Site-Data Example
  536. ----
  537. Clear-Site-Data: "cache", "cookies"
  538. ----
  539. You can send the `Clear-Site-Data` header on logout:
  540. .Clear-Site-Data Configuration
  541. [tabs]
  542. ======
  543. Java::
  544. +
  545. [source,java,role="primary"]
  546. ----
  547. @Bean
  548. SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
  549. ServerLogoutHandler securityContext = new SecurityContextServerLogoutHandler();
  550. ClearSiteDataServerHttpHeadersWriter writer = new ClearSiteDataServerHttpHeadersWriter(CACHE, COOKIES);
  551. ServerLogoutHandler clearSiteData = new HeaderWriterServerLogoutHandler(writer);
  552. DelegatingServerLogoutHandler logoutHandler = new DelegatingServerLogoutHandler(securityContext, clearSiteData);
  553. http
  554. // ...
  555. .logout()
  556. .logoutHandler(logoutHandler);
  557. return http.build();
  558. }
  559. ----
  560. Kotlin::
  561. +
  562. [source,kotlin,role="secondary"]
  563. ----
  564. @Bean
  565. fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
  566. val securityContext: ServerLogoutHandler = SecurityContextServerLogoutHandler()
  567. val writer = ClearSiteDataServerHttpHeadersWriter(CACHE, COOKIES)
  568. val clearSiteData: ServerLogoutHandler = HeaderWriterServerLogoutHandler(writer)
  569. val customLogoutHandler = DelegatingServerLogoutHandler(securityContext, clearSiteData)
  570. return http {
  571. // ...
  572. logout {
  573. logoutHandler = customLogoutHandler
  574. }
  575. }
  576. }
  577. ----
  578. ======