1
0
mirror of synced 2026-08-05 09:47:05 +00:00

Add Include-Code to the Password Storage page

References gh-16226

Signed-off-by: Himanshu Pareek <himanshupareekiit01@gmail.com>
This commit is contained in:
Himanshu Pareek
2025-10-15 21:44:45 +05:30
committed by Josh Cummings
parent 56a23d9ddc
commit dcb4e47cd5
15 changed files with 401 additions and 293 deletions
@@ -0,0 +1,57 @@
package org.springframework.security.docs.features.authentication.authenticationcompromisedpasswordcheck;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.password.CompromisedPasswordChecker;
import org.springframework.security.authentication.password.CompromisedPasswordException;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.password.HaveIBeenPwnedRestApiPasswordChecker;
public class CompromisedPasswordCheckerUsage {
// tag::configuration[]
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated()
)
.formLogin((login) -> login
.failureHandler(new CompromisedPasswordAuthenticationFailureHandler())
);
return http.build();
}
@Bean
public CompromisedPasswordChecker compromisedPasswordChecker() {
return new HaveIBeenPwnedRestApiPasswordChecker();
}
static class CompromisedPasswordAuthenticationFailureHandler implements AuthenticationFailureHandler {
private final SimpleUrlAuthenticationFailureHandler defaultFailureHandler = new SimpleUrlAuthenticationFailureHandler(
"/login?error");
private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
if (exception instanceof CompromisedPasswordException) {
this.redirectStrategy.sendRedirect(request, response, "/reset-password");
return;
}
this.defaultFailureHandler.onAuthenticationFailure(request, response, exception);
}
}
// end::configuration[]
}
@@ -0,0 +1,16 @@
package org.springframework.security.docs.features.authentication.authenticationpasswordstorageargon2;
import static org.junit.Assert.assertTrue;
import org.springframework.security.crypto.argon2.Argon2PasswordEncoder;
public class Argon2PasswordEncoderUsage {
public void testArgon2PasswordEncoder() {
// tag::argon2PasswordEncoder[]
// Create an encoder with all the defaults
Argon2PasswordEncoder encoder = Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8();
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));
// end::argon2PasswordEncoder[]
}
}
@@ -0,0 +1,16 @@
package org.springframework.security.docs.features.authentication.authenticationpasswordstoragebcrypt;
import static org.junit.Assert.assertTrue;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
public class BCryptPasswordEncoderUsage {
public void testBCryptPasswordEncoder() {
// tag::bcryptPasswordEncoder[]
// Create an encoder with strength 16
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16);
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));
// end::bcryptPasswordEncoder[]
}
}
@@ -0,0 +1,38 @@
package org.springframework.security.docs.features.authentication.authenticationpasswordstoragedepgettingstarted;
import java.util.List;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import static org.springframework.security.core.userdetails.User.UserBuilder;
public class WithDefaultPasswordEncoderUsage {
public UserDetails createSingleUser() {
// tag::createSingleUser[]
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("user")
.build();
System.out.println(user.getPassword());
// {bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
// end::createSingleUser[]
return user;
}
public List<UserDetails> createMultipleUsers() {
// tag::createMultipleUsers[]
UserBuilder users = User.withDefaultPasswordEncoder();
UserDetails user = users
.username("user")
.password("password")
.roles("USER")
.build();
UserDetails admin = users
.username("admin")
.password("password")
.roles("USER","ADMIN")
.build();
// end::createMultipleUsers[]
return List.of(user, admin);
}
}
@@ -0,0 +1,43 @@
package org.springframework.security.docs.features.authentication.authenticationpasswordstoragedpe;
import java.util.HashMap;
import java.util.Map;
import org.springframework.security.crypto.argon2.Argon2PasswordEncoder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder;
import org.springframework.security.crypto.password.StandardPasswordEncoder;
import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;
public class DelegatingPasswordEncoderUsage {
PasswordEncoder defaultDelegatingPasswordEncoder() {
// tag::createDefaultPasswordEncoder[]
PasswordEncoder passwordEncoder =
PasswordEncoderFactories.createDelegatingPasswordEncoder();
// end::createDefaultPasswordEncoder[]
return passwordEncoder;
}
PasswordEncoder customDelegatingPasswordEncoder() {
// tag::createCustomPasswordEncoder[]
String idForEncode = "bcrypt";
Map encoders = new HashMap<>();
encoders.put(idForEncode, new BCryptPasswordEncoder());
encoders.put("noop", NoOpPasswordEncoder.getInstance());
encoders.put("pbkdf2", Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_5());
encoders.put("pbkdf2@SpringSecurity_v5_8", Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8());
encoders.put("scrypt", SCryptPasswordEncoder.defaultsForSpringSecurity_v4_1());
encoders.put("scrypt@SpringSecurity_v5_8", SCryptPasswordEncoder.defaultsForSpringSecurity_v5_8());
encoders.put("argon2", Argon2PasswordEncoder.defaultsForSpringSecurity_v5_2());
encoders.put("argon2@SpringSecurity_v5_8", Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8());
encoders.put("sha256", new StandardPasswordEncoder());
PasswordEncoder passwordEncoder =
new DelegatingPasswordEncoder(idForEncode, encoders);
// end::createCustomPasswordEncoder[]
return passwordEncoder;
}
}
@@ -0,0 +1,16 @@
package org.springframework.security.docs.features.authentication.authenticationpasswordstoragepbkdf2;
import static org.junit.Assert.assertTrue;
import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder;
public class Pbkdf2PasswordEncoderUsage {
void testPbkdf2PasswordEncoder() {
// tag::pbkdf2PasswordEncoder[]
// Create an encoder with all the defaults
Pbkdf2PasswordEncoder encoder = Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8();
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));
// end::pbkdf2PasswordEncoder[]
}
}
@@ -0,0 +1,16 @@
package org.springframework.security.docs.features.authentication.authenticationpasswordstoragescrypt;
import static org.junit.Assert.assertTrue;
import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;
public class SCryptPasswordEncoderUsage {
void testSCryptPasswordEncoder() {
// tag::sCryptPasswordEncoder[]
// Create an encoder with all the defaults
SCryptPasswordEncoder encoder = SCryptPasswordEncoder.defaultsForSpringSecurity_v5_8();
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));
// end::sCryptPasswordEncoder[]
}
}
@@ -0,0 +1,55 @@
package org.springframework.security.kt.docs.features.authentication.authenticationcompromisedpasswordcheck
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import org.springframework.context.annotation.Bean
import org.springframework.security.authentication.password.CompromisedPasswordChecker
import org.springframework.security.authentication.password.CompromisedPasswordException
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.invoke
import org.springframework.security.core.AuthenticationException
import org.springframework.security.web.DefaultRedirectStrategy
import org.springframework.security.web.SecurityFilterChain
import org.springframework.security.web.authentication.AuthenticationFailureHandler
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler
import org.springframework.security.web.authentication.password.HaveIBeenPwnedRestApiPasswordChecker
class CompromisedPasswordCheckerUsage {
// tag::configuration[]
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
authorizeHttpRequests {
authorize(anyRequest, authenticated)
}
formLogin {
authenticationFailureHandler = CompromisedPasswordAuthenticationFailureHandler()
}
}
return http.build()
}
@Bean
open fun compromisedPasswordChecker(): CompromisedPasswordChecker {
return HaveIBeenPwnedRestApiPasswordChecker()
}
class CompromisedPasswordAuthenticationFailureHandler : AuthenticationFailureHandler {
private val defaultFailureHandler = SimpleUrlAuthenticationFailureHandler("/login?error")
private val redirectStrategy = DefaultRedirectStrategy()
override fun onAuthenticationFailure(
request: HttpServletRequest,
response: HttpServletResponse,
exception: AuthenticationException
) {
if (exception is CompromisedPasswordException) {
redirectStrategy.sendRedirect(request, response, "/reset-password")
return
}
defaultFailureHandler.onAuthenticationFailure(request, response, exception)
}
}
// end::configuration[]
}
@@ -0,0 +1,15 @@
package org.springframework.security.kt.docs.features.authentication.authenticationpasswordstorageargon2
import org.junit.Assert.assertTrue
import org.springframework.security.crypto.argon2.Argon2PasswordEncoder
class Argon2PasswordEncoderUsage {
fun testArgon2PasswordEncoder() {
// tag::argon2PasswordEncoder[]
// Create an encoder with all the defaults
val encoder = Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8()
val result: String = encoder.encode("myPassword")
assertTrue(encoder.matches("myPassword", result))
// end::argon2PasswordEncoder[]
}
}
@@ -0,0 +1,15 @@
package org.springframework.security.kt.docs.features.authentication.authenticationpasswordstoragebcrypt
import org.junit.Assert.assertTrue
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
class BCryptPasswordEncoderUsage {
fun testBCryptPasswordEncoder() {
// tag::bcryptPasswordEncoder[]
// Create an encoder with strength 16
val encoder = BCryptPasswordEncoder(16)
val result: String = encoder.encode("myPassword")
assertTrue(encoder.matches("myPassword", result))
// end::bcryptPasswordEncoder[]
}
}
@@ -0,0 +1,36 @@
package org.springframework.security.kt.docs.features.authentication.authenticationpasswordstoragedepgettingstarted
import org.springframework.security.core.userdetails.User
import org.springframework.security.core.userdetails.UserDetails
class WithDefaultPasswordEncoderUsage {
fun createSingleUser(): UserDetails {
// tag::createSingleUser[]
val user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("user")
.build()
println(user.password)
// {bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
// end::createSingleUser[]
return user
}
fun createMultipleUsers(): List<UserDetails> {
// tag::createMultipleUsers[]
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()
// end::createMultipleUsers[]
return listOf(user, admin)
}
}
@@ -0,0 +1,39 @@
package org.springframework.security.kt.docs.features.authentication.authenticationpasswordstoragedpe
import org.springframework.security.crypto.argon2.Argon2PasswordEncoder
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
import org.springframework.security.crypto.factory.PasswordEncoderFactories
import org.springframework.security.crypto.password.DelegatingPasswordEncoder
import org.springframework.security.crypto.password.NoOpPasswordEncoder
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder
import org.springframework.security.crypto.password.StandardPasswordEncoder
import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder
class DelegatingPasswordEncoderUsage {
fun defaultDelegatingPasswordEncoder(): PasswordEncoder {
// tag::createDefaultPasswordEncoder[]
val passwordEncoder: PasswordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder()
// end::createDefaultPasswordEncoder[]
return passwordEncoder
}
fun customDelegatingPasswordEncoder(): PasswordEncoder {
// tag::createCustomPasswordEncoder[]
val idForEncode = "bcrypt"
val encoders: MutableMap<String, PasswordEncoder> = mutableMapOf()
encoders[idForEncode] = BCryptPasswordEncoder()
encoders["noop"] = NoOpPasswordEncoder.getInstance()
encoders["pbkdf2"] = Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_5()
encoders["pbkdf2@SpringSecurity_v5_8"] = Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8()
encoders["scrypt"] = SCryptPasswordEncoder.defaultsForSpringSecurity_v4_1()
encoders["scrypt@SpringSecurity_v5_8"] = SCryptPasswordEncoder.defaultsForSpringSecurity_v5_8()
encoders["argon2"] = Argon2PasswordEncoder.defaultsForSpringSecurity_v5_2()
encoders["argon2@SpringSecurity_v5_8"] = Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8()
encoders["sha256"] = StandardPasswordEncoder()
val passwordEncoder: PasswordEncoder = DelegatingPasswordEncoder(idForEncode, encoders)
// end::createCustomPasswordEncoder[]
return passwordEncoder
}
}
@@ -0,0 +1,15 @@
package org.springframework.security.kt.docs.features.authentication.authenticationpasswordstoragepbkdf2
import org.junit.Assert.assertTrue
import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder
class Pbkdf2PasswordEncoderUsage {
fun testPbkdf2PasswordEncoder() {
// tag::pbkdf2PasswordEncoder[]
// Create an encoder with all the defaults
val encoder = Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8()
val result: String = encoder.encode("myPassword")
assertTrue(encoder.matches("myPassword", result))
// end::pbkdf2PasswordEncoder[]
}
}
@@ -0,0 +1,15 @@
package org.springframework.security.kt.docs.features.authentication.authenticationpasswordstoragescrypt
import org.junit.Assert.assertTrue
import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder
class SCryptPasswordEncoderUsage {
fun testSCryptPasswordEncoder() {
// tag::sCryptPasswordEncoder[]
// Create an encoder with all the defaults
val encoder = SCryptPasswordEncoder.defaultsForSpringSecurity_v5_8()
val result: String = encoder.encode("myPassword")
assertTrue(encoder.matches("myPassword", result))
// end::sCryptPasswordEncoder[]
}
}