|
|
|
@ -68,18 +68,26 @@ You can easily construct an instance of `DelegatingPasswordEncoder` using `Pass |
|
|
|
|
|
|
|
|
|
|
|
.Create Default DelegatingPasswordEncoder |
|
|
|
.Create Default DelegatingPasswordEncoder |
|
|
|
==== |
|
|
|
==== |
|
|
|
[source,java] |
|
|
|
.Java |
|
|
|
|
|
|
|
[source,java,role="primary"] |
|
|
|
---- |
|
|
|
---- |
|
|
|
PasswordEncoder passwordEncoder = |
|
|
|
PasswordEncoder passwordEncoder = |
|
|
|
PasswordEncoderFactories.createDelegatingPasswordEncoder(); |
|
|
|
PasswordEncoderFactories.createDelegatingPasswordEncoder(); |
|
|
|
---- |
|
|
|
---- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.Kotlin |
|
|
|
|
|
|
|
[source,kotlin,role="secondary"] |
|
|
|
|
|
|
|
---- |
|
|
|
|
|
|
|
val passwordEncoder: PasswordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder() |
|
|
|
|
|
|
|
---- |
|
|
|
==== |
|
|
|
==== |
|
|
|
|
|
|
|
|
|
|
|
Alternatively, you may create your own custom instance. For example: |
|
|
|
Alternatively, you may create your own custom instance. For example: |
|
|
|
|
|
|
|
|
|
|
|
.Create Custom DelegatingPasswordEncoder |
|
|
|
.Create Custom DelegatingPasswordEncoder |
|
|
|
==== |
|
|
|
==== |
|
|
|
[source,java] |
|
|
|
.Java |
|
|
|
|
|
|
|
[source,java,role="primary"] |
|
|
|
---- |
|
|
|
---- |
|
|
|
String idForEncode = "bcrypt"; |
|
|
|
String idForEncode = "bcrypt"; |
|
|
|
Map encoders = new HashMap<>(); |
|
|
|
Map encoders = new HashMap<>(); |
|
|
|
@ -92,6 +100,20 @@ encoders.put("sha256", new StandardPasswordEncoder()); |
|
|
|
PasswordEncoder passwordEncoder = |
|
|
|
PasswordEncoder passwordEncoder = |
|
|
|
new DelegatingPasswordEncoder(idForEncode, encoders); |
|
|
|
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]] |
|
|
|
[[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 |
|
|
|
.withDefaultPasswordEncoder Example |
|
|
|
==== |
|
|
|
==== |
|
|
|
[source,java,attrs="-attributes"] |
|
|
|
.Java |
|
|
|
|
|
|
|
[source,java,role="primary",attrs="-attributes"] |
|
|
|
---- |
|
|
|
---- |
|
|
|
User user = User.withDefaultPasswordEncoder() |
|
|
|
User user = User.withDefaultPasswordEncoder() |
|
|
|
.username("user") |
|
|
|
.username("user") |
|
|
|
@ -190,13 +213,26 @@ User user = User.withDefaultPasswordEncoder() |
|
|
|
System.out.println(user.getPassword()); |
|
|
|
System.out.println(user.getPassword()); |
|
|
|
// {bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG |
|
|
|
// {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. |
|
|
|
If you are creating multiple users, you can also reuse the builder. |
|
|
|
|
|
|
|
|
|
|
|
.withDefaultPasswordEncoder Reusing the Builder |
|
|
|
.withDefaultPasswordEncoder Reusing the Builder |
|
|
|
==== |
|
|
|
==== |
|
|
|
[source,java] |
|
|
|
.Java |
|
|
|
|
|
|
|
[source,java,role="primary"] |
|
|
|
---- |
|
|
|
---- |
|
|
|
UserBuilder users = User.withDefaultPasswordEncoder(); |
|
|
|
UserBuilder users = User.withDefaultPasswordEncoder(); |
|
|
|
User user = users |
|
|
|
User user = users |
|
|
|
@ -210,6 +246,22 @@ User admin = users |
|
|
|
.roles("USER","ADMIN") |
|
|
|
.roles("USER","ADMIN") |
|
|
|
.build(); |
|
|
|
.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. |
|
|
|
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. |
|
|
|
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. |
|
|
|
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 |
|
|
|
// Create an encoder with strength 16 |
|
|
|
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16); |
|
|
|
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16); |
|
|
|
@ -281,6 +336,16 @@ String result = encoder.encode("myPassword"); |
|
|
|
assertTrue(encoder.matches("myPassword", result)); |
|
|
|
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]] |
|
|
|
[[authentication-password-storage-argon2]] |
|
|
|
== Argon2PasswordEncoder |
|
|
|
== 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. |
|
|
|
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. |
|
|
|
The current implementation if the `Argon2PasswordEncoder` requires BouncyCastle. |
|
|
|
|
|
|
|
|
|
|
|
[source,java] |
|
|
|
.Argon2PasswordEncoder |
|
|
|
|
|
|
|
==== |
|
|
|
|
|
|
|
.Java |
|
|
|
|
|
|
|
[source,java,role="primary"] |
|
|
|
---- |
|
|
|
---- |
|
|
|
// Create an encoder with all the defaults |
|
|
|
// Create an encoder with all the defaults |
|
|
|
Argon2PasswordEncoder encoder = new Argon2PasswordEncoder(); |
|
|
|
Argon2PasswordEncoder encoder = new Argon2PasswordEncoder(); |
|
|
|
@ -298,6 +366,16 @@ String result = encoder.encode("myPassword"); |
|
|
|
assertTrue(encoder.matches("myPassword", result)); |
|
|
|
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]] |
|
|
|
[[authentication-password-storage-pbkdf2]] |
|
|
|
== Pbkdf2PasswordEncoder |
|
|
|
== 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. |
|
|
|
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. |
|
|
|
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 |
|
|
|
// Create an encoder with all the defaults |
|
|
|
Pbkdf2PasswordEncoder encoder = new Pbkdf2PasswordEncoder(); |
|
|
|
Pbkdf2PasswordEncoder encoder = new Pbkdf2PasswordEncoder(); |
|
|
|
@ -314,6 +395,16 @@ String result = encoder.encode("myPassword"); |
|
|
|
assertTrue(encoder.matches("myPassword", result)); |
|
|
|
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]] |
|
|
|
[[authentication-password-storage-scrypt]] |
|
|
|
== SCryptPasswordEncoder |
|
|
|
== 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. |
|
|
|
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. |
|
|
|
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 |
|
|
|
// Create an encoder with all the defaults |
|
|
|
SCryptPasswordEncoder encoder = new SCryptPasswordEncoder(); |
|
|
|
SCryptPasswordEncoder encoder = new SCryptPasswordEncoder(); |
|
|
|
@ -329,6 +423,16 @@ String result = encoder.encode("myPassword"); |
|
|
|
assertTrue(encoder.matches("myPassword", result)); |
|
|
|
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]] |
|
|
|
[[authentication-password-storage-other]] |
|
|
|
== Other PasswordEncoders |
|
|
|
== Other PasswordEncoders |
|
|
|
|
|
|
|
|
|
|
|
|