migration.adoc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  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. === Multiple SecurityContextRepository
  25. In Spring Security 5, the default xref:servlet/authentication/persistence.adoc#securitycontextrepository[`SecurityContextRepository`] was `HttpSessionSecurityContextRepository`.
  26. In Spring Security 6, the default `SecurityContextRepository` is `DelegatingSecurityContextRepository`.
  27. If you configured the `SecurityContextRepository` only for the purpose of updating to 6.0, you can remove it completely.
  28. === Deprecation in SecurityContextRepository
  29. There are no further migration steps for this deprecation.
  30. [[requestcache-query-optimization]]
  31. === Optimize Querying of `RequestCache`
  32. In Spring Security 5, the default behavior is to query the xref:servlet/architecture.adoc#savedrequests[saved request] on every request.
  33. 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.
  34. In Spring Security 6, the default is that `RequestCache` will only be queried for a cached request if the HTTP parameter `continue` is defined.
  35. This allows Spring Security to avoid unnecessarily reading the `HttpSession` with the `RequestCache`.
  36. In Spring Security 5 the default is to use `HttpSessionRequestCache` which will be queried for a cached request on every request.
  37. 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:
  38. include::partial$servlet/architecture/request-cache-continue.adoc[]
  39. === Use `AuthorizationManager` for Method Security
  40. There are no further migration steps for this feature.
  41. === Use `AuthorizationManager` for Message Security
  42. In 6.0, `<websocket-message-broker>` defaults `use-authorization-manager` to `true`.
  43. So, to complete migration, remove any `websocket-message-broker@use-authorization-manager=true` attribute.
  44. For example:
  45. ====
  46. .Xml
  47. [source,xml,role="primary"]
  48. ----
  49. <websocket-message-broker use-authorization-manager="true"/>
  50. ----
  51. ====
  52. changes to:
  53. ====
  54. .Xml
  55. [source,xml,role="primary"]
  56. ----
  57. <websocket-message-broker/>
  58. ----
  59. ====
  60. There are no further migrations steps for Java or Kotlin for this feature.
  61. === Use `AuthorizationManager` for Request Security
  62. In 6.0, `<http>` defaults `once-per-request` to `false`, `filter-all-dispatcher-types` to `true`, and `use-authorization-manager` to `true`.
  63. 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`.
  64. So, to complete migration, any defaults values can be removed.
  65. For example, if you opted in to the 6.0 default for `filter-all-dispatcher-types` or `authorizeHttpRequests#filterAllDispatcherTypes` like so:
  66. ====
  67. .Java
  68. [source,java,role="primary"]
  69. ----
  70. http
  71. .authorizeHttpRequests((authorize) -> authorize
  72. .filterAllDispatcherTypes(true)
  73. // ...
  74. )
  75. ----
  76. .Kotlin
  77. [source,java,role="secondary"]
  78. ----
  79. http {
  80. authorizeHttpRequests {
  81. filterAllDispatcherTypes = true
  82. // ...
  83. }
  84. }
  85. ----
  86. .Xml
  87. [source,xml,role="secondary"]
  88. ----
  89. <http use-authorization-manager="true" filter-all-dispatcher-types="true"/>
  90. ----
  91. ====
  92. then the defaults may be removed:
  93. ====
  94. .Java
  95. [source,java,role="primary"]
  96. ----
  97. http
  98. .authorizeHttpRequests((authorize) -> authorize
  99. // ...
  100. )
  101. ----
  102. .Kotlin
  103. [source,java,role="secondary"]
  104. ----
  105. http {
  106. authorizeHttpRequests {
  107. // ...
  108. }
  109. }
  110. ----
  111. .Xml
  112. [source,xml,role="secondary"]
  113. ----
  114. <http/>
  115. ----
  116. ====
  117. [NOTE]
  118. ====
  119. `once-per-request` applies only when `use-authorization-manager="false"` and `filter-all-dispatcher-types` only applies when `use-authorization-manager="true"`
  120. ====
  121. === Propagate ``AuthenticationServiceException``s
  122. {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`].
  123. 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.
  124. So, if you opted into this behavior by setting `rethrowAuthenticationServiceException` too `true`, you can now remove it like so:
  125. ====
  126. .Java
  127. [source,java,role="primary"]
  128. ----
  129. AuthenticationFilter authenticationFilter = new AuthenticationFilter(...);
  130. AuthenticationEntryPointFailureHandler handler = new AuthenticationEntryPointFailureHandler(...);
  131. handler.setRethrowAuthenticationServiceException(true);
  132. authenticationFilter.setAuthenticationFailureHandler(handler);
  133. ----
  134. .Kotlin
  135. [source,kotlin,role="secondary"]
  136. ----
  137. val authenticationFilter: AuthenticationFilter = new AuthenticationFilter(...)
  138. val handler: AuthenticationEntryPointFailureHandler = new AuthenticationEntryPointFailureHandler(...)
  139. handler.setRethrowAuthenticationServiceException(true)
  140. authenticationFilter.setAuthenticationFailureHandler(handler)
  141. ----
  142. .Xml
  143. [source,xml,role="secondary"]
  144. ----
  145. <bean id="authenticationFilter" class="org.springframework.security.web.authentication.AuthenticationFilter">
  146. <!-- ... -->
  147. <property ref="authenticationFailureHandler"/>
  148. </bean>
  149. <bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.AuthenticationEntryPointFailureHandler">
  150. <property name="rethrowAuthenticationServiceException" value="true"/>
  151. </bean>
  152. ----
  153. ====
  154. changes to:
  155. ====
  156. .Java
  157. [source,java,role="primary"]
  158. ----
  159. AuthenticationFilter authenticationFilter = new AuthenticationFilter(...);
  160. AuthenticationEntryPointFailureHandler handler = new AuthenticationEntryPointFailureHandler(...);
  161. authenticationFilter.setAuthenticationFailureHandler(handler);
  162. ----
  163. .Kotlin
  164. [source,kotlin,role="secondary"]
  165. ----
  166. val authenticationFilter: AuthenticationFilter = new AuthenticationFilter(...)
  167. val handler: AuthenticationEntryPointFailureHandler = new AuthenticationEntryPointFailureHandler(...)
  168. authenticationFilter.setAuthenticationFailureHandler(handler)
  169. ----
  170. .Xml
  171. [source,xml,role="secondary"]
  172. ----
  173. <bean id="authenticationFilter" class="org.springframework.security.web.authentication.AuthenticationFilter">
  174. <!-- ... -->
  175. <property ref="authenticationFailureHandler"/>
  176. </bean>
  177. <bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.AuthenticationEntryPointFailureHandler">
  178. <!-- ... -->
  179. </bean>
  180. ----
  181. ====
  182. [[servlet-opt-in-sha256-rememberme]]
  183. === Use SHA-256 in Remember Me
  184. In 6.0, the `TokenBasedRememberMeServices` uses SHA-256 to encode and match the token.
  185. To complete the migration, any default values can be removed.
  186. For example, if you opted in to the 6.0 default for `encodingAlgorithm` and `matchingAlgorithm` like so:
  187. ====
  188. .Java
  189. [source,java,role="primary"]
  190. ----
  191. @Configuration
  192. @EnableWebSecurity
  193. public class SecurityConfig {
  194. @Bean
  195. SecurityFilterChain securityFilterChain(HttpSecurity http, RememberMeServices rememberMeServices) throws Exception {
  196. http
  197. // ...
  198. .rememberMe((remember) -> remember
  199. .rememberMeServices(rememberMeServices)
  200. );
  201. return http.build();
  202. }
  203. @Bean
  204. RememberMeServices rememberMeServices(UserDetailsService userDetailsService) {
  205. RememberMeTokenAlgorithm encodingAlgorithm = RememberMeTokenAlgorithm.SHA256;
  206. TokenBasedRememberMeServices rememberMe = new TokenBasedRememberMeServices(myKey, userDetailsService, encodingAlgorithm);
  207. rememberMe.setMatchingAlgorithm(RememberMeTokenAlgorithm.SHA256);
  208. return rememberMe;
  209. }
  210. }
  211. ----
  212. .XML
  213. [source,xml,role="secondary"]
  214. ----
  215. <http>
  216. <remember-me services-ref="rememberMeServices"/>
  217. </http>
  218. <bean id="rememberMeServices" class=
  219. "org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
  220. <property name="userDetailsService" ref="myUserDetailsService"/>
  221. <property name="key" value="springRocks"/>
  222. <property name="matchingAlgorithm" value="SHA256"/>
  223. <property name="encodingAlgorithm" value="SHA256"/>
  224. </bean>
  225. ----
  226. ====
  227. then the defaults can be removed:
  228. ====
  229. .Java
  230. [source,java,role="primary"]
  231. ----
  232. @Configuration
  233. @EnableWebSecurity
  234. public class SecurityConfig {
  235. @Bean
  236. SecurityFilterChain securityFilterChain(HttpSecurity http, RememberMeServices rememberMeServices) throws Exception {
  237. http
  238. // ...
  239. .rememberMe((remember) -> remember
  240. .rememberMeServices(rememberMeServices)
  241. );
  242. return http.build();
  243. }
  244. @Bean
  245. RememberMeServices rememberMeServices(UserDetailsService userDetailsService) {
  246. return new TokenBasedRememberMeServices(myKey, userDetailsService);
  247. }
  248. }
  249. ----
  250. .XML
  251. [source,xml,role="secondary"]
  252. ----
  253. <http>
  254. <remember-me services-ref="rememberMeServices"/>
  255. </http>
  256. <bean id="rememberMeServices" class=
  257. "org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
  258. <property name="userDetailsService" ref="myUserDetailsService"/>
  259. <property name="key" value="springRocks"/>
  260. </bean>
  261. ----
  262. ====
  263. [[use-new-requestmatchers]]
  264. === Use the new `requestMatchers` methods
  265. There are no further migration steps for this feature.
  266. [[use-new-security-matchers]]
  267. === Use the new `securityMatchers` methods
  268. There are no further migration steps for this feature.
  269. === Remove CAS support
  270. In Spring Security 6.0, the CAS support https://github.com/spring-projects/spring-security/issues/10441[has been removed].
  271. There is no direct replacement for it, however, it is possible to https://apereo.github.io/cas/6.6.x/authentication/OAuth-Authentication.html[configure your CAS server to act as an OAuth 2.0 Authentication Provider] and use the xref::servlet/oauth2/index.adoc[OAuth 2.0 support in Spring Security].
  272. === Default authorities for oauth2Login()
  273. In Spring Security 5, the default `GrantedAuthority` given to a user that authenticates with an OAuth2 or OpenID Connect 1.0 provider (via `oauth2Login()`) is `ROLE_USER`.
  274. In Spring Security 6, the default authority given to a user authenticating with an OAuth2 provider is `OAUTH2_USER`.
  275. The default authority given to a user authenticating with an OpenID Connect 1.0 provider is `OIDC_USER`.
  276. If you configured the `GrantedAuthoritiesMapper` only for the purpose of updating to 6.0, you can remove it completely.
  277. == Reactive
  278. === Use `AuthorizationManager` for Method Security
  279. In 6.0, `@EnableReactiveMethodSecurity` defaults `useAuthorizationManager` to `true`.
  280. So, to complete migration, {security-api-url}org/springframework/security/config/annotation/method/configuration/EnableReactiveMethodSecurity.html[`@EnableReactiveMethodSecurity`] remove the `useAuthorizationManager` attribute:
  281. ====
  282. .Java
  283. [source,java,role="primary"]
  284. ----
  285. @EnableReactiveMethodSecurity(useAuthorizationManager = true)
  286. ----
  287. .Kotlin
  288. [source,kotlin,role="secondary"]
  289. ----
  290. @EnableReactiveMethodSecurity(useAuthorizationManager = true)
  291. ----
  292. ====
  293. changes to:
  294. ====
  295. .Java
  296. [source,java,role="primary"]
  297. ----
  298. @EnableReactiveMethodSecurity
  299. ----
  300. .Kotlin
  301. [source,kotlin,role="secondary"]
  302. ----
  303. @EnableReactiveMethodSecurity
  304. ----
  305. ====
  306. '''
  307. === Propagate ``AuthenticationServiceException``s
  308. {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`].
  309. 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.
  310. So, if you opted into this behavior by setting `rethrowAuthenticationServiceException` too `true`, you can now remove it like so:
  311. ====
  312. .Java
  313. [source,java,role="primary"]
  314. ----
  315. AuthenticationFailureHandler bearerFailureHandler = new ServerAuthenticationEntryPointFailureHandler(bearerEntryPoint);
  316. bearerFailureHandler.setRethrowAuthenticationServiceException(true);
  317. AuthenticationFailureHandler basicFailureHandler = new ServerAuthenticationEntryPointFailureHandler(basicEntryPoint);
  318. basicFailureHandler.setRethrowAuthenticationServiceException(true);
  319. ----
  320. .Kotlin
  321. [source,kotlin,role="secondary"]
  322. ----
  323. val bearerFailureHandler: AuthenticationFailureHandler = ServerAuthenticationEntryPointFailureHandler(bearerEntryPoint)
  324. bearerFailureHandler.setRethrowAuthenticationServiceException(true)
  325. val basicFailureHandler: AuthenticationFailureHandler = ServerAuthenticationEntryPointFailureHandler(basicEntryPoint)
  326. basicFailureHandler.setRethrowAuthenticationServiceException(true)
  327. ----
  328. ====
  329. changes to:
  330. ====
  331. .Java
  332. [source,java,role="primary"]
  333. ----
  334. AuthenticationFailureHandler bearerFailureHandler = new ServerAuthenticationEntryPointFailureHandler(bearerEntryPoint);
  335. AuthenticationFailureHandler basicFailureHandler = new ServerAuthenticationEntryPointFailureHandler(basicEntryPoint);
  336. ----
  337. .Kotlin
  338. [source,kotlin,role="secondary"]
  339. ----
  340. val bearerFailureHandler: AuthenticationFailureHandler = ServerAuthenticationEntryPointFailureHandler(bearerEntryPoint)
  341. val basicFailureHandler: AuthenticationFailureHandler = ServerAuthenticationEntryPointFailureHandler(basicEntryPoint)
  342. ----
  343. ====
  344. [NOTE]
  345. ====
  346. If you configured the `ServerAuthenticationFailureHandler` only for the purpose of updating to 6.0, you can remove it completely.
  347. ====
  348. [[revert]]
  349. 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.
  350. It's more important to stay on 6.0 and get the security improvements.
  351. == Revert Servlet
  352. == Revert Reactive