2
0

headers.adoc 14 KB

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