index.adoc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. [[migration]]
  2. = Preparing for 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 the steps below to minimize changes when
  5. ifdef::spring-security-version[]
  6. xref:6.0.0@migration.adoc[updating to 6.0]
  7. endif::[]
  8. ifndef::spring-security-version[]
  9. updating to 6.0
  10. endif::[]
  11. .
  12. == Update to Spring Security 5.8
  13. The first step is to ensure you are the latest patch release of Spring Boot 2.7.
  14. Next, you should ensure you are on the latest patch release of Spring Security 5.8.
  15. If you are using Spring Boot, you will need to override the Spring Boot version from Spring Security 5.7 to 5.8.
  16. Spring Security 5.8 is fully compatible with Spring Security 5.7 and thus Spring Boot 2.7.
  17. For directions, on how to update to Spring Security 5.8 visit the xref:getting-spring-security.adoc[] section of the reference guide.
  18. == Update Password Encoding
  19. In 6.0, password encoding minimums are updated for PBKDF2, SCrypt, and Argon2.
  20. [NOTE]
  21. ====
  22. If you are using the default password encoder, then there are no preparation steps to follow and this section can be skipped.
  23. ====
  24. === Update `Pbkdf2PasswordEncoder`
  25. If you are xref:features/authentication/password-storage.adoc#authentication-password-storage-pbkdf2[using `Pbkdf2PasswordEncoder`], the constructors are replaced with static factories that refer to the Spring Security version that the given settings apply to.
  26. ==== Replace Deprecated Constructor Usage
  27. If you use the default constructor, you should begin by changing:
  28. ====
  29. .Java
  30. [source,java,role="primary"]
  31. ----
  32. @Bean
  33. PasswordEncoder passwordEncoder() {
  34. return new Pbkdf2PasswordEncoder();
  35. }
  36. ----
  37. .Kotlin
  38. [source,kotlin,role="secondary"]
  39. ----
  40. @Bean
  41. fun passwordEncoder(): PasswordEncoder {
  42. return Pbkdf2PasswordEncoder()
  43. }
  44. ----
  45. ====
  46. to:
  47. ====
  48. .Java
  49. [source,java,role="primary"]
  50. ----
  51. @Bean
  52. PasswordEncoder passwordEncoder() {
  53. return Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_5();
  54. }
  55. ----
  56. .Kotlin
  57. [source,kotlin,role="secondary"]
  58. ----
  59. @Bean
  60. fun passwordEncoder(): PasswordEncoder {
  61. return Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_5()
  62. }
  63. ----
  64. ====
  65. Or, if you have custom settings, change to the constructor that specifies all settings, like so:
  66. ====
  67. .Java
  68. [source,java,role="primary"]
  69. ----
  70. @Bean
  71. PasswordEncoder passwordEncoder() {
  72. PasswordEncoder current = new Pbkdf2PasswordEncoder("mysecret".getBytes(UTF_8), 320000);
  73. return current;
  74. }
  75. ----
  76. .Kotlin
  77. [source,kotlin,role="secondary"]
  78. ----
  79. @Bean
  80. fun passwordEncoder(): PasswordEncoder {
  81. val current: PasswordEncoder = Pbkdf2PasswordEncoder("mysecret".getBytes(UTF_8), 320000)
  82. return current
  83. }
  84. ----
  85. ====
  86. Change them to use the fully-specified constructor, like the following:
  87. ====
  88. .Java
  89. [source,java,role="primary"]
  90. ----
  91. @Bean
  92. PasswordEncoder passwordEncoder() {
  93. PasswordEncoder current = new Pbkdf2PasswordEncoder("mysecret".getBytes(UTF_8), 16, 185000, 256);
  94. return current;
  95. }
  96. ----
  97. .Kotlin
  98. [source,kotlin,role="secondary"]
  99. ----
  100. @Bean
  101. fun passwordEncoder(): PasswordEncoder {
  102. val current: PasswordEncoder = Pbkdf2PasswordEncoder("mysecret".getBytes(UTF_8), 16, 185000, 256)
  103. return current
  104. }
  105. ----
  106. ====
  107. ==== Use `DelegatedPasswordEncoder`
  108. Once you are not using the deprecated constructor, the next step is to prepare your code to upgrade to the latest standards by using `DelegatedPasswordEncoder`.
  109. The following code configures the delegating encoder to detect passwords that are using `current` and replace them with the latest:
  110. ====
  111. .Java
  112. [source,java,role="primary"]
  113. ----
  114. @Bean
  115. PasswordEncoder passwordEncoder() {
  116. String prefix = "pbkdf2@5.8";
  117. PasswordEncoder current = // ... see previous step
  118. PasswordEncoder upgraded = Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8();
  119. DelegatedPasswordEncoder delegating = new DelegatedPasswordEncoder(prefix, Map.of(prefix, upgraded));
  120. delegating.setDefaultPasswordEncoderFormatches(current);
  121. return delegating;
  122. }
  123. ----
  124. .Kotlin
  125. [source,kotlin,role="secondary"]
  126. ----
  127. @Bean
  128. fun passwordEncoder(): PasswordEncoder {
  129. String prefix = "pbkdf2@5.8"
  130. PasswordEncoder current = // ... see previous step
  131. PasswordEncoder upgraded = Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8()
  132. DelegatedPasswordEncoder delegating = new DelegatedPasswordEncoder(prefix, Map.of(prefix, upgraded))
  133. delegating.setDefaultPasswordEncoderFormatches(current)
  134. return delegating
  135. }
  136. ----
  137. ====
  138. === Update `SCryptPasswordEncoder`
  139. If you are xref:features/authentication/password-storage.adoc#authentication-password-storage-scrypt[using `SCryptPasswordEncoder`], the constructors are replaced with static factories that refer to the Spring Security version that the given settings apply to.
  140. ==== Replace Deprecated Constructor Usage
  141. If you use the default constructor, you should begin by changing:
  142. ====
  143. .Java
  144. [source,java,role="primary"]
  145. ----
  146. @Bean
  147. PasswordEncoder passwordEncoder() {
  148. return new SCryptPasswordEncoder();
  149. }
  150. ----
  151. .Kotlin
  152. [source,kotlin,role="secondary"]
  153. ----
  154. @Bean
  155. fun passwordEncoder(): PasswordEncoder {
  156. return SCryptPasswordEncoder()
  157. }
  158. ----
  159. ====
  160. to:
  161. ====
  162. .Java
  163. [source,java,role="primary"]
  164. ----
  165. @Bean
  166. PasswordEncoder passwordEncoder() {
  167. return SCryptPasswordEncoder.defaultsForSpringSecurity_v4_1();
  168. }
  169. ----
  170. .Kotlin
  171. [source,kotlin,role="secondary"]
  172. ----
  173. @Bean
  174. fun passwordEncoder(): PasswordEncoder {
  175. return SCryptPasswordEncoder.defaultsForSpringSecurity_v4_1()
  176. }
  177. ----
  178. ====
  179. ==== Use `DelegatedPasswordEncoder`
  180. Once you are not using the deprecated constructor, the next step is to prepare your code to upgrade to the latest standards by using `DelegatedPasswordEncoder`.
  181. The following code configures the delegating encoder to detect passwords that are using `current` and replace them with the latest:
  182. ====
  183. .Java
  184. [source,java,role="primary"]
  185. ----
  186. @Bean
  187. PasswordEncoder passwordEncoder() {
  188. String prefix = "scrypt@5.8";
  189. PasswordEncoder current = // ... see previous step
  190. PasswordEncoder upgraded = SCryptPasswordEncoder.defaultsForSpringSecurity_v5_8();
  191. DelegatedPasswordEncoder delegating = new DelegatedPasswordEncoder(prefix, Map.of(prefix, upgraded));
  192. delegating.setDefaultPasswordEncoderFormatches(current);
  193. return delegating;
  194. }
  195. ----
  196. .Kotlin
  197. [source,kotlin,role="secondary"]
  198. ----
  199. @Bean
  200. fun passwordEncoder(): PasswordEncoder {
  201. String prefix = "scrypt@5.8"
  202. PasswordEncoder current = // ... see previous step
  203. PasswordEncoder upgraded = SCryptPasswordEncoder.defaultsForSpringSecurity_v5_8()
  204. DelegatedPasswordEncoder delegating = new DelegatedPasswordEncoder(prefix, Map.of(prefix, upgraded))
  205. delegating.setDefaultPasswordEncoderFormatches(current)
  206. return delegating
  207. }
  208. ----
  209. ====
  210. === Update `Argon2PasswordEncoder`
  211. If you are xref:features/authentication/password-storage.adoc#authentication-password-storage-argon2[using `Argon2PasswordEncoder`], the constructors are replaced with static factories that refer to the Spring Security version that the given settings apply to.
  212. ==== Replace Deprecated Constructor Usage
  213. If you use the default constructor, you should begin by changing:
  214. ====
  215. .Java
  216. [source,java,role="primary"]
  217. ----
  218. @Bean
  219. PasswordEncoder passwordEncoder() {
  220. return new Argon2PasswordEncoder();
  221. }
  222. ----
  223. .Kotlin
  224. [source,kotlin,role="secondary"]
  225. ----
  226. @Bean
  227. fun passwordEncoder(): PasswordEncoder {
  228. return Argon2PasswordEncoder()
  229. }
  230. ----
  231. ====
  232. to:
  233. ====
  234. .Java
  235. [source,java,role="primary"]
  236. ----
  237. @Bean
  238. PasswordEncoder passwordEncoder() {
  239. return Argon2PasswordEncoder.defaultsForSpringSecurity_v5_2();
  240. }
  241. ----
  242. .Kotlin
  243. [source,kotlin,role="secondary"]
  244. ----
  245. @Bean
  246. fun passwordEncoder(): PasswordEncoder {
  247. return Argon2PasswordEncoder.defaultsForSpringSecurity_v5_2()
  248. }
  249. ----
  250. ====
  251. ==== Use `DelegatedPasswordEncoder`
  252. Once you are not using the deprecated constructor, the next step is to prepare your code to upgrade to the latest standards by using `DelegatedPasswordEncoder`.
  253. The following code configures the delegating encoder to detect passwords that are using `current` and replace them with the latest:
  254. ====
  255. .Java
  256. [source,java,role="primary"]
  257. ----
  258. @Bean
  259. PasswordEncoder passwordEncoder() {
  260. String prefix = "argon@5.8";
  261. PasswordEncoder current = // ... see previous step
  262. PasswordEncoder upgraded = Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8();
  263. DelegatedPasswordEncoder delegating = new DelegatedPasswordEncoder(prefix, Map.of(prefix, upgraded));
  264. delegating.setDefaultPasswordEncoderFormatches(current);
  265. return delegating;
  266. }
  267. ----
  268. .Kotlin
  269. [source,kotlin,role="secondary"]
  270. ----
  271. @Bean
  272. fun passwordEncoder(): PasswordEncoder {
  273. String prefix = "argon@5.8"
  274. PasswordEncoder current = // ... see previous step
  275. PasswordEncoder upgraded = Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8()
  276. DelegatedPasswordEncoder delegating = new DelegatedPasswordEncoder(prefix, Map.of(prefix, upgraded))
  277. delegating.setDefaultPasswordEncoderFormatches(current)
  278. return delegating
  279. }
  280. ----
  281. ====
  282. == Stop using `Encryptors.queryableText`
  283. `Encryptors.queryableText(CharSequence,CharSequence)` is unsafe since https://tanzu.vmware.com/security/cve-2020-5408[the same input data will produce the same output].
  284. It was deprecated and will be removed in 6.0; Spring Security no longer supports encrypting data in this way.
  285. To upgrade, you will either need to re-encrypt with a supported mechanism or store it decrypted.
  286. Consider the following pseudocode for reading each encrypted entry from a table, decrypting it, and then re-encrypting it using a supported mechanism:
  287. ====
  288. .Java
  289. [source,java,role="primary"]
  290. ----
  291. TextEncryptor deprecated = Encryptors.queryableText(password, salt);
  292. BytesEncryptor aes = new AesBytesEncryptor(password, salt, KeyGenerators.secureRandom(12), CipherAlgorithm.GCM);
  293. TextEncryptor supported = new HexEncodingTextEncryptor(aes);
  294. for (MyEntry entry : entries) {
  295. String value = deprecated.decrypt(entry.getEncryptedValue()); <1>
  296. entry.setEncryptedValue(supported.encrypt(value)); <2>
  297. entryService.save(entry)
  298. }
  299. ----
  300. ====
  301. <1> - The above uses the deprecated `queryableText` to convert the value to plaintext.
  302. <2> - Then, the value is re-encrypted with a supported Spring Security mechanism.
  303. Please see the reference manual for more information on what xref:features/integrations/cryptography.adoc[encryption mechanisms Spring Security supports].
  304. == Perform Application-Specific Steps
  305. Next, there are steps you need to perform based on whether it is a xref:migration/servlet/index.adoc[Servlet] or xref:migration/reactive.adoc[Reactive] application.