headers.adoc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  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 block reflected XSS attacks by using the <<headers-xss-protection,X-XSS-Protection header>.
  229. You can disable `X-XSS-Protection`:
  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. [[webflux-headers-csp]]
  262. == Content Security Policy (CSP)
  263. 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.
  264. The web application author must declare the security policies to enforce and/or monitor for the protected resources.
  265. For example, consider the following security policy:
  266. .Content Security Policy Example
  267. ====
  268. [source,http]
  269. ----
  270. Content-Security-Policy: script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/
  271. ----
  272. ====
  273. Given the preceding policy, you can enable the CSP header:
  274. .Content Security Policy
  275. ====
  276. .Java
  277. [source,java,role="primary"]
  278. ----
  279. @Bean
  280. SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
  281. http
  282. // ...
  283. .headers(headers -> headers
  284. .contentSecurityPolicy(policy -> policy
  285. .policyDirectives("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/")
  286. )
  287. );
  288. return http.build();
  289. }
  290. ----
  291. .Kotlin
  292. [source,kotlin,role="secondary"]
  293. ----
  294. @Bean
  295. fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
  296. return http {
  297. // ...
  298. headers {
  299. contentSecurityPolicy {
  300. policyDirectives = "script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/"
  301. }
  302. }
  303. }
  304. }
  305. ----
  306. ====
  307. To enable the CSP `report-only` header, provide the following configuration:
  308. .Content Security Policy Report Only
  309. ====
  310. .Java
  311. [source,java,role="primary"]
  312. ----
  313. @Bean
  314. SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
  315. http
  316. // ...
  317. .headers(headers -> headers
  318. .contentSecurityPolicy(policy -> policy
  319. .policyDirectives("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/")
  320. .reportOnly()
  321. )
  322. );
  323. return http.build();
  324. }
  325. ----
  326. .Kotlin
  327. [source,kotlin,role="secondary"]
  328. ----
  329. @Bean
  330. fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
  331. return http {
  332. // ...
  333. headers {
  334. contentSecurityPolicy {
  335. policyDirectives = "script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/"
  336. reportOnly = true
  337. }
  338. }
  339. }
  340. }
  341. ----
  342. ====
  343. [[webflux-headers-referrer]]
  344. == Referrer Policy
  345. By default, Spring Security does not add xref:features/exploits/headers.adoc#headers-referrer[Referrer Policy] headers.
  346. You can enable the Referrer Policy header using configuration as shown below:
  347. .Referrer Policy Configuration
  348. ====
  349. .Java
  350. [source,java,role="primary"]
  351. ----
  352. @Bean
  353. SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
  354. http
  355. // ...
  356. .headers(headers -> headers
  357. .referrerPolicy(referrer -> referrer
  358. .policy(ReferrerPolicy.SAME_ORIGIN)
  359. )
  360. );
  361. return http.build();
  362. }
  363. ----
  364. .Kotlin
  365. [source,kotlin,role="secondary"]
  366. ----
  367. @Bean
  368. fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
  369. return http {
  370. // ...
  371. headers {
  372. referrerPolicy {
  373. policy = ReferrerPolicy.SAME_ORIGIN
  374. }
  375. }
  376. }
  377. }
  378. ----
  379. ====
  380. [[webflux-headers-feature]]
  381. == Feature Policy
  382. By default, Spring Security does not add xref:features/exploits/headers.adoc#headers-feature[Feature Policy] headers.
  383. Consider the following `Feature-Policy` header:
  384. .Feature-Policy Example
  385. ====
  386. [source]
  387. ----
  388. Feature-Policy: geolocation 'self'
  389. ----
  390. ====
  391. You can enable the preceding Feature Policy header:
  392. .Feature-Policy Configuration
  393. ====
  394. .Java
  395. [source,java,role="primary"]
  396. ----
  397. @Bean
  398. SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
  399. http
  400. // ...
  401. .headers(headers -> headers
  402. .featurePolicy("geolocation 'self'")
  403. );
  404. return http.build();
  405. }
  406. ----
  407. .Kotlin
  408. [source,kotlin,role="secondary"]
  409. ----
  410. @Bean
  411. fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
  412. return http {
  413. // ...
  414. headers {
  415. featurePolicy("geolocation 'self'")
  416. }
  417. }
  418. }
  419. ----
  420. ====
  421. [[webflux-headers-permissions]]
  422. == Permissions Policy
  423. By default, Spring Security does not add xref:features/exploits/headers.adoc#headers-permissions[Permissions Policy] headers.
  424. Consider the following `Permissions-Policy` header:
  425. .Permissions-Policy Example
  426. ====
  427. [source]
  428. ----
  429. Permissions-Policy: geolocation=(self)
  430. ----
  431. ====
  432. You can enable the preceding Permissions Policy header:
  433. .Permissions-Policy Configuration
  434. ====
  435. .Java
  436. [source,java,role="primary"]
  437. ----
  438. @Bean
  439. SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
  440. http
  441. // ...
  442. .headers(headers -> headers
  443. .permissionsPolicy(permissions -> permissions
  444. .policy("geolocation=(self)")
  445. )
  446. );
  447. return http.build();
  448. }
  449. ----
  450. .Kotlin
  451. [source,kotlin,role="secondary"]
  452. ----
  453. @Bean
  454. fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
  455. return http {
  456. // ...
  457. headers {
  458. permissionsPolicy {
  459. policy = "geolocation=(self)"
  460. }
  461. }
  462. }
  463. }
  464. ----
  465. ====
  466. [[webflux-headers-clear-site-data]]
  467. == Clear Site Data
  468. By default, Spring Security does not add xref:features/exploits/headers.adoc#headers-clear-site-data[Clear-Site-Data] headers.
  469. Consider the following `Clear-Site-Data` header:
  470. .Clear-Site-Data Example
  471. ====
  472. ----
  473. Clear-Site-Data: "cache", "cookies"
  474. ----
  475. ====
  476. You can send the `Clear-Site-Data` header on logout:
  477. .Clear-Site-Data Configuration
  478. ====
  479. .Java
  480. [source,java,role="primary"]
  481. ----
  482. @Bean
  483. SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
  484. ServerLogoutHandler securityContext = new SecurityContextServerLogoutHandler();
  485. ClearSiteDataServerHttpHeadersWriter writer = new ClearSiteDataServerHttpHeadersWriter(CACHE, COOKIES);
  486. ServerLogoutHandler clearSiteData = new HeaderWriterServerLogoutHandler(writer);
  487. DelegatingServerLogoutHandler logoutHandler = new DelegatingServerLogoutHandler(securityContext, clearSiteData);
  488. http
  489. // ...
  490. .logout()
  491. .logoutHandler(logoutHandler);
  492. return http.build();
  493. }
  494. ----
  495. .Kotlin
  496. [source,kotlin,role="secondary"]
  497. ----
  498. @Bean
  499. fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
  500. val securityContext: ServerLogoutHandler = SecurityContextServerLogoutHandler()
  501. val writer = ClearSiteDataServerHttpHeadersWriter(CACHE, COOKIES)
  502. val clearSiteData: ServerLogoutHandler = HeaderWriterServerLogoutHandler(writer)
  503. val customLogoutHandler = DelegatingServerLogoutHandler(securityContext, clearSiteData)
  504. return http {
  505. // ...
  506. logout {
  507. logoutHandler = customLogoutHandler
  508. }
  509. }
  510. }
  511. ----
  512. ====