migration.adoc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. [[migration]]
  2. = Migrating to 6.0
  3. The Spring Security team has prepared the 5.8 release to simplify upgrading to Spring Security 6.0.
  4. Use 5.8 and
  5. ifdef::spring-security-version[]
  6. xref:5.8.0@migration.adoc[its preparation steps]
  7. endif::[]
  8. ifndef::spring-security-version[]
  9. its preparation steps
  10. endif::[]
  11. to simplify updating to 6.0
  12. After updating to 5.8, follow this guide to perform any needed migration steps.
  13. Also, this guide includes ways to <<revert,revert to 5.x>> behaviors and its defaults, should you run into trouble.
  14. == Servlet
  15. In Spring Security 5, the default behavior is for the xref:servlet/authentication/architecture.adoc#servlet-authentication-securitycontext[`SecurityContext`] to automatically be saved to the xref:servlet/authentication/persistence.adoc#securitycontextrepository[`SecurityContextRepository`] using the xref:servlet/authentication/persistence.adoc#securitycontextpersistencefilter[`SecurityContextPersistenceFilter`].
  16. Saving must be done just prior to the `HttpServletResponse` being committed and just before `SecurityContextPersistenceFilter`.
  17. Unfortunately, automatic persistence of the `SecurityContext` can surprise users when it is done prior to the request completing (i.e. just prior to committing the `HttpServletResponse`).
  18. It also is complex to keep track of the state to determine if a save is necessary causing unnecessary writes to the `SecurityContextRepository` (i.e. `HttpSession`) at times.
  19. In Spring Security 6, the default behavior is that the xref:servlet/authentication/persistence.adoc#securitycontextholderfilter[`SecurityContextHolderFilter`] will only read the `SecurityContext` from `SecurityContextRepository` and populate it in the `SecurityContextHolder`.
  20. Users now must explicitly save the `SecurityContext` with the `SecurityContextRepository` if they want the `SecurityContext` to persist between requests.
  21. This removes ambiguity and improves performance by only requiring writing to the `SecurityContextRepository` (i.e. `HttpSession`) when it is necessary.
  22. If you are explicitly opting into Spring Security 6's new defaults, the following configuration can be removed to accept the Spring Security 6 defaults.
  23. include::partial$servlet/architecture/security-context-explicit.adoc[]
  24. [[requestcache-query-optimization]]
  25. === Optimize Querying of `RequestCache`
  26. In Spring Security 5, the default behavior is to query the xref:servlet/architecture.adoc#savedrequests[saved request] on every request.
  27. This means that in a typical setup, that in order to use the xref:servlet/architecture.adoc#requestcache[`RequestCache`] the `HttpSession` is queried on every request.
  28. In Spring Security 6, the default is that `RequestCache` will only be queried for a cached request if the HTTP parameter `continue` is defined.
  29. This allows Spring Security to avoid unnecessarily reading the `HttpSession` with the `RequestCache`.
  30. In Spring Security 5 the default is to use `HttpSessionRequestCache` which will be queried for a cached request on every request.
  31. If you are not overriding the defaults (i.e. using `NullRequestCache`), then the following configuration can be used to explicitly opt into the Spring Security 6 behavior in Spring Security 5.8:
  32. include::partial$servlet/architecture/request-cache-continue.adoc[]
  33. === Use `AuthorizationManager` for Method Security
  34. There are no further migration steps for this feature.
  35. === Use `AuthorizationManager` for Message Security
  36. In 6.0, `<websocket-message-broker>` defaults `use-authorization-manager` to `true`.
  37. So, to complete migration, remove any `websocket-message-broker@use-authorization-manager=true` attribute.
  38. For example:
  39. ====
  40. .Xml
  41. [source,xml,role="primary"]
  42. ----
  43. <websocket-message-broker use-authorization-manager="true"/>
  44. ----
  45. ====
  46. changes to:
  47. ====
  48. .Xml
  49. [source,xml,role="primary"]
  50. ----
  51. <websocket-message-broker/>
  52. ----
  53. ====
  54. There are no further migrations steps for Java or Kotlin for this feature.
  55. === Use `AuthorizationManager` for Request Security
  56. In 6.0, `<http>` defaults `once-per-request` to `false`, `filter-all-dispatcher-types` to `true`, and `use-authorization-manager` to `true`.
  57. Also, xref:servlet/authorization/authorize-requests.adoc#filtersecurityinterceptor-every-request[`authorizeRequests#filterSecurityInterceptorOncePerRequest`] defaults to `false` and xref:servlet/authorization/authorize-http-requests.adoc[`authorizeHttpRequests#filterAllDispatcherTypes`] defaults to `true`.
  58. So, to complete migration, any defaults values can be removed.
  59. For example, if you opted in to the 6.0 default for `filter-all-dispatcher-types` or `authorizeHttpRequests#filterAllDispatcherTypes` like so:
  60. ====
  61. .Java
  62. [source,java,role="primary"]
  63. ----
  64. http
  65. .authorizeHttpRequests((authorize) -> authorize
  66. .filterAllDispatcherTypes(true)
  67. // ...
  68. )
  69. ----
  70. .Kotlin
  71. [source,java,role="secondary"]
  72. ----
  73. http {
  74. authorizeHttpRequests {
  75. filterAllDispatcherTypes = true
  76. // ...
  77. }
  78. }
  79. ----
  80. .Xml
  81. [source,xml,role="secondary"]
  82. ----
  83. <http use-authorization-manager="true" filter-all-dispatcher-types="true"/>
  84. ----
  85. ====
  86. then the defaults may be removed:
  87. ====
  88. .Java
  89. [source,java,role="primary"]
  90. ----
  91. http
  92. .authorizeHttpRequests((authorize) -> authorize
  93. // ...
  94. )
  95. ----
  96. .Kotlin
  97. [source,java,role="secondary"]
  98. ----
  99. http {
  100. authorizeHttpRequests {
  101. // ...
  102. }
  103. }
  104. ----
  105. .Xml
  106. [source,xml,role="secondary"]
  107. ----
  108. <http/>
  109. ----
  110. ====
  111. [NOTE]
  112. ====
  113. `once-per-request` applies only when `use-authorization-manager="false"` and `filter-all-dispatcher-types` only applies when `use-authorization-manager="true"`
  114. ====
  115. === Propagate ``AuthenticationServiceException``s
  116. {security-api-url}org/springframework/security/web/authentication/AuthenticationFilter.html[`AuthenticationFilter`] propagates {security-api-url}org/springframework/security/authentication/AuthenticationServiceException.html[``AuthenticationServiceException``]s to the {security-api-url}org/springframework/security/authentication/AuthenticationEntryPoint.html[`AuthenticationEntryPoint`].
  117. Because ``AuthenticationServiceException``s represent a server-side error instead of a client-side error, in 6.0, this changes to propagate them to the container.
  118. So, if you opted into this behavior by setting `rethrowAuthenticationServiceException` too `true`, you can now remove it like so:
  119. ====
  120. .Java
  121. [source,java,role="primary"]
  122. ----
  123. AuthenticationFilter authenticationFilter = new AuthenticationFilter(...);
  124. AuthenticationEntryPointFailureHandler handler = new AuthenticationEntryPointFailureHandler(...);
  125. handler.setRethrowAuthenticationServiceException(true);
  126. authenticationFilter.setAuthenticationFailureHandler(handler);
  127. ----
  128. .Kotlin
  129. [source,kotlin,role="secondary"]
  130. ----
  131. val authenticationFilter: AuthenticationFilter = new AuthenticationFilter(...)
  132. val handler: AuthenticationEntryPointFailureHandler = new AuthenticationEntryPointFailureHandler(...)
  133. handler.setRethrowAuthenticationServiceException(true)
  134. authenticationFilter.setAuthenticationFailureHandler(handler)
  135. ----
  136. .Xml
  137. [source,xml,role="secondary"]
  138. ----
  139. <bean id="authenticationFilter" class="org.springframework.security.web.authentication.AuthenticationFilter">
  140. <!-- ... -->
  141. <property ref="authenticationFailureHandler"/>
  142. </bean>
  143. <bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.AuthenticationEntryPointFailureHandler">
  144. <property name="rethrowAuthenticationServiceException" value="true"/>
  145. </bean>
  146. ----
  147. ====
  148. changes to:
  149. ====
  150. .Java
  151. [source,java,role="primary"]
  152. ----
  153. AuthenticationFilter authenticationFilter = new AuthenticationFilter(...);
  154. AuthenticationEntryPointFailureHandler handler = new AuthenticationEntryPointFailureHandler(...);
  155. authenticationFilter.setAuthenticationFailureHandler(handler);
  156. ----
  157. .Kotlin
  158. [source,kotlin,role="secondary"]
  159. ----
  160. val authenticationFilter: AuthenticationFilter = new AuthenticationFilter(...)
  161. val handler: AuthenticationEntryPointFailureHandler = new AuthenticationEntryPointFailureHandler(...)
  162. authenticationFilter.setAuthenticationFailureHandler(handler)
  163. ----
  164. .Xml
  165. [source,xml,role="secondary"]
  166. ----
  167. <bean id="authenticationFilter" class="org.springframework.security.web.authentication.AuthenticationFilter">
  168. <!-- ... -->
  169. <property ref="authenticationFailureHandler"/>
  170. </bean>
  171. <bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.AuthenticationEntryPointFailureHandler">
  172. <!-- ... -->
  173. </bean>
  174. ----
  175. ====
  176. [[servlet-opt-in-sha256-rememberme]]
  177. === Use SHA-256 in Remember Me
  178. In 6.0, the `TokenBasedRememberMeServices` uses SHA-256 to encode and match the token.
  179. To complete the migration, any default values can be removed.
  180. For example, if you opted in to the 6.0 default for `encodingAlgorithm` and `matchingAlgorithm` like so:
  181. ====
  182. .Java
  183. [source,java,role="primary"]
  184. ----
  185. @Configuration
  186. @EnableWebSecurity
  187. public class SecurityConfig {
  188. @Bean
  189. SecurityFilterChain securityFilterChain(HttpSecurity http, RememberMeServices rememberMeServices) throws Exception {
  190. http
  191. // ...
  192. .rememberMe((remember) -> remember
  193. .rememberMeServices(rememberMeServices)
  194. );
  195. return http.build();
  196. }
  197. @Bean
  198. RememberMeServices rememberMeServices(UserDetailsService userDetailsService) {
  199. RememberMeTokenAlgorithm encodingAlgorithm = RememberMeTokenAlgorithm.SHA256;
  200. TokenBasedRememberMeServices rememberMe = new TokenBasedRememberMeServices(myKey, userDetailsService, encodingAlgorithm);
  201. rememberMe.setMatchingAlgorithm(RememberMeTokenAlgorithm.SHA256);
  202. return rememberMe;
  203. }
  204. }
  205. ----
  206. .XML
  207. [source,xml,role="secondary"]
  208. ----
  209. <http>
  210. <remember-me services-ref="rememberMeServices"/>
  211. </http>
  212. <bean id="rememberMeServices" class=
  213. "org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
  214. <property name="userDetailsService" ref="myUserDetailsService"/>
  215. <property name="key" value="springRocks"/>
  216. <property name="matchingAlgorithm" value="SHA256"/>
  217. <property name="encodingAlgorithm" value="SHA256"/>
  218. </bean>
  219. ----
  220. ====
  221. then the defaults can be removed:
  222. ====
  223. .Java
  224. [source,java,role="primary"]
  225. ----
  226. @Configuration
  227. @EnableWebSecurity
  228. public class SecurityConfig {
  229. @Bean
  230. SecurityFilterChain securityFilterChain(HttpSecurity http, RememberMeServices rememberMeServices) throws Exception {
  231. http
  232. // ...
  233. .rememberMe((remember) -> remember
  234. .rememberMeServices(rememberMeServices)
  235. );
  236. return http.build();
  237. }
  238. @Bean
  239. RememberMeServices rememberMeServices(UserDetailsService userDetailsService) {
  240. return new TokenBasedRememberMeServices(myKey, userDetailsService);
  241. }
  242. }
  243. ----
  244. .XML
  245. [source,xml,role="secondary"]
  246. ----
  247. <http>
  248. <remember-me services-ref="rememberMeServices"/>
  249. </http>
  250. <bean id="rememberMeServices" class=
  251. "org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
  252. <property name="userDetailsService" ref="myUserDetailsService"/>
  253. <property name="key" value="springRocks"/>
  254. </bean>
  255. ----
  256. ====
  257. [[use-new-requestmatchers]]
  258. === Use the new `requestMatchers` methods
  259. There are no further migration steps for this feature.
  260. [[use-new-security-matchers]]
  261. === Use the new `securityMatchers` methods
  262. There are no further migration steps for this feature.
  263. == Reactive
  264. === Use `AuthorizationManager` for Method Security
  265. In 6.0, `@EnableReactiveMethodSecurity` defaults `useAuthorizationManager` to `true`.
  266. So, to complete migration, {security-api-url}org/springframework/security/config/annotation/method/configuration/EnableReactiveMethodSecurity.html[`@EnableReactiveMethodSecurity`] remove the `useAuthorizationManager` attribute:
  267. ====
  268. .Java
  269. [source,java,role="primary"]
  270. ----
  271. @EnableReactiveMethodSecurity(useAuthorizationManager = true)
  272. ----
  273. .Kotlin
  274. [source,kotlin,role="secondary"]
  275. ----
  276. @EnableReactiveMethodSecurity(useAuthorizationManager = true)
  277. ----
  278. ====
  279. changes to:
  280. ====
  281. .Java
  282. [source,java,role="primary"]
  283. ----
  284. @EnableReactiveMethodSecurity
  285. ----
  286. .Kotlin
  287. [source,kotlin,role="secondary"]
  288. ----
  289. @EnableReactiveMethodSecurity
  290. ----
  291. ====
  292. '''
  293. === Propagate ``AuthenticationServiceException``s
  294. {security-api-url}org/springframework/security/web/server/authentication/AuthenticationWebFilter.html[`AuthenticationWebFilter`] propagates {security-api-url}org/springframework/security/authentication/AuthenticationServiceException.html[``AuthenticationServiceException``]s to the {security-api-url}org/springframework/security/web/server/ServerAuthenticationEntryPoint.html[`ServerAuthenticationEntryPoint`].
  295. Because ``AuthenticationServiceException``s represent a server-side error instead of a client-side error, in 6.0, this changes to propagate them to the container.
  296. So, if you opted into this behavior by setting `rethrowAuthenticationServiceException` too `true`, you can now remove it like so:
  297. ====
  298. .Java
  299. [source,java,role="primary"]
  300. ----
  301. AuthenticationFailureHandler bearerFailureHandler = new ServerAuthenticationEntryPointFailureHandler(bearerEntryPoint);
  302. bearerFailureHandler.setRethrowAuthenticationServiceException(true);
  303. AuthenticationFailureHandler basicFailureHandler = new ServerAuthenticationEntryPointFailureHandler(basicEntryPoint);
  304. basicFailureHandler.setRethrowAuthenticationServiceException(true);
  305. ----
  306. .Kotlin
  307. [source,kotlin,role="secondary"]
  308. ----
  309. val bearerFailureHandler: AuthenticationFailureHandler = ServerAuthenticationEntryPointFailureHandler(bearerEntryPoint)
  310. bearerFailureHandler.setRethrowAuthenticationServiceException(true)
  311. val basicFailureHandler: AuthenticationFailureHandler = ServerAuthenticationEntryPointFailureHandler(basicEntryPoint)
  312. basicFailureHandler.setRethrowAuthenticationServiceException(true)
  313. ----
  314. ====
  315. changes to:
  316. ====
  317. .Java
  318. [source,java,role="primary"]
  319. ----
  320. AuthenticationFailureHandler bearerFailureHandler = new ServerAuthenticationEntryPointFailureHandler(bearerEntryPoint);
  321. AuthenticationFailureHandler basicFailureHandler = new ServerAuthenticationEntryPointFailureHandler(basicEntryPoint);
  322. ----
  323. .Kotlin
  324. [source,kotlin,role="secondary"]
  325. ----
  326. val bearerFailureHandler: AuthenticationFailureHandler = ServerAuthenticationEntryPointFailureHandler(bearerEntryPoint)
  327. val basicFailureHandler: AuthenticationFailureHandler = ServerAuthenticationEntryPointFailureHandler(basicEntryPoint)
  328. ----
  329. ====
  330. [NOTE]
  331. ====
  332. If you configured the `ServerAuthenticationFailureHandler` only for the purpose of updating to 6.0, you can remove it completely.
  333. ====
  334. [[revert]]
  335. If you are running into trouble with any of the 6.0 changes, please first try to apply the following changes to get you up and running.
  336. It's more important to stay on 6.0 and get the security improvements.
  337. == Revert Servlet
  338. == Revert Reactive