|
@@ -68,18 +68,26 @@ You can easily construct an instance of `DelegatingPasswordEncoder` using `Pass
|
|
|
|
|
|
.Create Default DelegatingPasswordEncoder
|
|
|
====
|
|
|
-[source,java]
|
|
|
+.Java
|
|
|
+[source,java,role="primary"]
|
|
|
----
|
|
|
PasswordEncoder passwordEncoder =
|
|
|
PasswordEncoderFactories.createDelegatingPasswordEncoder();
|
|
|
----
|
|
|
+
|
|
|
+.Kotlin
|
|
|
+[source,kotlin,role="secondary"]
|
|
|
+----
|
|
|
+val passwordEncoder: PasswordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder()
|
|
|
+----
|
|
|
====
|
|
|
|
|
|
Alternatively, you may create your own custom instance. For example:
|
|
|
|
|
|
.Create Custom DelegatingPasswordEncoder
|
|
|
====
|
|
|
-[source,java]
|
|
|
+.Java
|
|
|
+[source,java,role="primary"]
|
|
|
----
|
|
|
String idForEncode = "bcrypt";
|
|
|
Map encoders = new HashMap<>();
|
|
@@ -92,6 +100,20 @@ encoders.put("sha256", new StandardPasswordEncoder());
|
|
|
PasswordEncoder passwordEncoder =
|
|
|
new DelegatingPasswordEncoder(idForEncode, encoders);
|
|
|
----
|
|
|
+
|
|
|
+.Kotlin
|
|
|
+[source,kotlin,role="secondary"]
|
|
|
+----
|
|
|
+val idForEncode = "bcrypt"
|
|
|
+val encoders: MutableMap<String, PasswordEncoder> = mutableMapOf()
|
|
|
+encoders[idForEncode] = BCryptPasswordEncoder()
|
|
|
+encoders["noop"] = NoOpPasswordEncoder.getInstance()
|
|
|
+encoders["pbkdf2"] = Pbkdf2PasswordEncoder()
|
|
|
+encoders["scrypt"] = SCryptPasswordEncoder()
|
|
|
+encoders["sha256"] = StandardPasswordEncoder()
|
|
|
+
|
|
|
+val passwordEncoder: PasswordEncoder = DelegatingPasswordEncoder(idForEncode, encoders)
|
|
|
+----
|
|
|
====
|
|
|
|
|
|
[[authentication-password-storage-dpe-format]]
|
|
@@ -180,7 +202,8 @@ There are convenience mechanisms to make this easier, but this is still not inte
|
|
|
|
|
|
.withDefaultPasswordEncoder Example
|
|
|
====
|
|
|
-[source,java,attrs="-attributes"]
|
|
|
+.Java
|
|
|
+[source,java,role="primary",attrs="-attributes"]
|
|
|
----
|
|
|
User user = User.withDefaultPasswordEncoder()
|
|
|
.username("user")
|
|
@@ -190,13 +213,26 @@ User user = User.withDefaultPasswordEncoder()
|
|
|
System.out.println(user.getPassword());
|
|
|
// {bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
|
|
|
----
|
|
|
+
|
|
|
+.Kotlin
|
|
|
+[source,kotlin,role="secondary",attrs="-attributes"]
|
|
|
+----
|
|
|
+val user = User.withDefaultPasswordEncoder()
|
|
|
+ .username("user")
|
|
|
+ .password("password")
|
|
|
+ .roles("user")
|
|
|
+ .build()
|
|
|
+println(user.password)
|
|
|
+// {bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
|
|
|
+----
|
|
|
====
|
|
|
|
|
|
If you are creating multiple users, you can also reuse the builder.
|
|
|
|
|
|
.withDefaultPasswordEncoder Reusing the Builder
|
|
|
====
|
|
|
-[source,java]
|
|
|
+.Java
|
|
|
+[source,java,role="primary"]
|
|
|
----
|
|
|
UserBuilder users = User.withDefaultPasswordEncoder();
|
|
|
User user = users
|
|
@@ -210,6 +246,22 @@ User admin = users
|
|
|
.roles("USER","ADMIN")
|
|
|
.build();
|
|
|
----
|
|
|
+
|
|
|
+.Kotlin
|
|
|
+[source,kotlin,role="secondary"]
|
|
|
+----
|
|
|
+val users = User.withDefaultPasswordEncoder()
|
|
|
+val user = users
|
|
|
+ .username("user")
|
|
|
+ .password("password")
|
|
|
+ .roles("USER")
|
|
|
+ .build()
|
|
|
+val admin = users
|
|
|
+ .username("admin")
|
|
|
+ .password("password")
|
|
|
+ .roles("USER", "ADMIN")
|
|
|
+ .build()
|
|
|
+----
|
|
|
====
|
|
|
|
|
|
This does hash the password that is stored, but the passwords are still exposed in memory and in the compiled source code.
|
|
@@ -273,7 +325,10 @@ The `BCryptPasswordEncoder` implementation uses the widely supported https://en.
|
|
|
In order to make it more resistent to password cracking, bcrypt is deliberately slow.
|
|
|
Like other adaptive one-way functions, it should be tuned to take about 1 second to verify a password on your system.
|
|
|
|
|
|
-[source,java]
|
|
|
+.BCryptPasswordEncoder
|
|
|
+====
|
|
|
+.Java
|
|
|
+[source,java,role="primary"]
|
|
|
----
|
|
|
// Create an encoder with strength 16
|
|
|
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16);
|
|
@@ -281,6 +336,16 @@ String result = encoder.encode("myPassword");
|
|
|
assertTrue(encoder.matches("myPassword", result));
|
|
|
----
|
|
|
|
|
|
+.Kotlin
|
|
|
+[source,kotlin,role="secondary"]
|
|
|
+----
|
|
|
+// Create an encoder with strength 16
|
|
|
+val encoder = BCryptPasswordEncoder(16)
|
|
|
+val result: String = encoder.encode("myPassword")
|
|
|
+assertTrue(encoder.matches("myPassword", result))
|
|
|
+----
|
|
|
+====
|
|
|
+
|
|
|
[[authentication-password-storage-argon2]]
|
|
|
== Argon2PasswordEncoder
|
|
|
|
|
@@ -290,7 +355,10 @@ In order to defeat password cracking on custom hardware, Argon2 is a deliberatel
|
|
|
Like other adaptive one-way functions, it should be tuned to take about 1 second to verify a password on your system.
|
|
|
The current implementation if the `Argon2PasswordEncoder` requires BouncyCastle.
|
|
|
|
|
|
-[source,java]
|
|
|
+.Argon2PasswordEncoder
|
|
|
+====
|
|
|
+.Java
|
|
|
+[source,java,role="primary"]
|
|
|
----
|
|
|
// Create an encoder with all the defaults
|
|
|
Argon2PasswordEncoder encoder = new Argon2PasswordEncoder();
|
|
@@ -298,6 +366,16 @@ String result = encoder.encode("myPassword");
|
|
|
assertTrue(encoder.matches("myPassword", result));
|
|
|
----
|
|
|
|
|
|
+.Kotlin
|
|
|
+[source,kotlin,role="secondary"]
|
|
|
+----
|
|
|
+// Create an encoder with all the defaults
|
|
|
+val encoder = Argon2PasswordEncoder()
|
|
|
+val result: String = encoder.encode("myPassword")
|
|
|
+assertTrue(encoder.matches("myPassword", result))
|
|
|
+----
|
|
|
+====
|
|
|
+
|
|
|
[[authentication-password-storage-pbkdf2]]
|
|
|
== Pbkdf2PasswordEncoder
|
|
|
|
|
@@ -306,7 +384,10 @@ In order to defeat password cracking PBKDF2 is a deliberately slow algorithm.
|
|
|
Like other adaptive one-way functions, it should be tuned to take about 1 second to verify a password on your system.
|
|
|
This algorithm is a good choice when FIPS certification is required.
|
|
|
|
|
|
-[source,java]
|
|
|
+.Pbkdf2PasswordEncoder
|
|
|
+====
|
|
|
+.Java
|
|
|
+[source,java,role="primary"]
|
|
|
----
|
|
|
// Create an encoder with all the defaults
|
|
|
Pbkdf2PasswordEncoder encoder = new Pbkdf2PasswordEncoder();
|
|
@@ -314,6 +395,16 @@ String result = encoder.encode("myPassword");
|
|
|
assertTrue(encoder.matches("myPassword", result));
|
|
|
----
|
|
|
|
|
|
+.Kotlin
|
|
|
+[source,kotlin,role="secondary"]
|
|
|
+----
|
|
|
+// Create an encoder with all the defaults
|
|
|
+val encoder = Pbkdf2PasswordEncoder()
|
|
|
+val result: String = encoder.encode("myPassword")
|
|
|
+assertTrue(encoder.matches("myPassword", result))
|
|
|
+----
|
|
|
+====
|
|
|
+
|
|
|
[[authentication-password-storage-scrypt]]
|
|
|
== SCryptPasswordEncoder
|
|
|
|
|
@@ -321,7 +412,10 @@ The `SCryptPasswordEncoder` implementation uses https://en.wikipedia.org/wiki/Sc
|
|
|
In order to defeat password cracking on custom hardware scrypt is a deliberately slow algorithm that requires large amounts of memory.
|
|
|
Like other adaptive one-way functions, it should be tuned to take about 1 second to verify a password on your system.
|
|
|
|
|
|
-[source,java]
|
|
|
+.SCryptPasswordEncoder
|
|
|
+====
|
|
|
+.Java
|
|
|
+[source,java,role="primary"]
|
|
|
----
|
|
|
// Create an encoder with all the defaults
|
|
|
SCryptPasswordEncoder encoder = new SCryptPasswordEncoder();
|
|
@@ -329,6 +423,16 @@ String result = encoder.encode("myPassword");
|
|
|
assertTrue(encoder.matches("myPassword", result));
|
|
|
----
|
|
|
|
|
|
+.Kotlin
|
|
|
+[source,kotlin,role="secondary"]
|
|
|
+----
|
|
|
+// Create an encoder with all the defaults
|
|
|
+val encoder = SCryptPasswordEncoder()
|
|
|
+val result: String = encoder.encode("myPassword")
|
|
|
+assertTrue(encoder.matches("myPassword", result))
|
|
|
+----
|
|
|
+====
|
|
|
+
|
|
|
[[authentication-password-storage-other]]
|
|
|
== Other PasswordEncoders
|
|
|
|