소스 검색

Merge branch '6.3.x'

Closes gh-15306
Marcus Hert Da Coregio 1 년 전
부모
커밋
dd7472272a
1개의 변경된 파일44개의 추가작업 그리고 41개의 파일을 삭제
  1. 44 41
      docs/modules/ROOT/pages/features/authentication/password-storage.adoc

+ 44 - 41
docs/modules/ROOT/pages/features/authentication/password-storage.adoc

@@ -602,7 +602,11 @@ To facilitate that, Spring Security provides integration with the https://haveib
 
 You can either use the `CompromisedPasswordChecker` API by yourself or, if you are using xref:servlet/authentication/passwords/dao-authentication-provider.adoc[the `DaoAuthenticationProvider]` via xref:servlet/authentication/passwords/index.adoc[Spring Security authentication mechanisms], you can provide a `CompromisedPasswordChecker` bean, and it will be automatically picked up by Spring Security configuration.
 
-.Using CompromisedPasswordChecker as a bean
+By doing that, when you try to authenticate via Form Login using a weak password, let's say `123456`, you will receive a 401 or be redirected to the `/login?error` page (depending on your user-agent).
+However, just a 401 or the redirect is not so useful in that case, it will cause some confusion because the user provided the right password and still was not allowed to log in.
+In such cases, you can handle the `CompromisedPasswordException` via the `AuthenticationFailureHandler` to perform your desired logic, like redirecting the user-agent to `/reset-password`, for example:
+
+.Using CompromisedPasswordChecker
 [tabs]
 ======
 Java::
@@ -615,8 +619,9 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
         .authorizeHttpRequests(authorize -> authorize
             .anyRequest().authenticated()
         )
-        .formLogin(withDefaults())
-        .httpBasic(withDefaults());
+        .formLogin((login) -> login
+            .failureHandler(new CompromisedPasswordAuthenticationFailureHandler())
+        );
     return http.build();
 }
 
@@ -624,6 +629,25 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
 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);
+    }
+
+}
 ----
 
 Kotlin::
@@ -636,8 +660,9 @@ open fun filterChain(http:HttpSecurity): SecurityFilterChain {
         authorizeHttpRequests {
             authorize(anyRequest, authenticated)
         }
-        formLogin {}
-        httpBasic {}
+        formLogin {
+            failureHandler = CompromisedPasswordAuthenticationFailureHandler()
+        }
     }
     return http.build()
 }
@@ -646,44 +671,22 @@ open fun filterChain(http:HttpSecurity): SecurityFilterChain {
 open fun compromisedPasswordChecker(): CompromisedPasswordChecker {
     return HaveIBeenPwnedRestApiPasswordChecker()
 }
-----
-======
-
-By doing that, when you try to authenticate via HTTP Basic or Form Login using a weak password, let's say `123456`, you will receive a 401 response status code.
-However, just a 401 is not so useful in that case, it will cause some confusion because the user provided the right password and still was not allowed to log in.
-In such cases, you can handle the `CompromisedPasswordException` to perform your desired logic, like redirecting the user-agent to `/reset-password`, for example:
-
-[tabs]
-======
-Java::
-+
-[source,java,role="primary"]
-----
-@ControllerAdvice
-public class MyControllerAdvice {
-
-    @ExceptionHandler(CompromisedPasswordException.class)
-    public String handleCompromisedPasswordException(CompromisedPasswordException ex, RedirectAttributes attributes) {
-        attributes.addFlashAttribute("error", ex.message);
-        return "redirect:/reset-password";
-    }
-
-}
-----
-
-Kotlin::
-+
-[source,kotlin,role="secondary"]
-----
-@ControllerAdvice
-class MyControllerAdvice {
 
-    @ExceptionHandler(CompromisedPasswordException::class)
-    fun handleCompromisedPasswordException(ex: CompromisedPasswordException, attributes: RedirectAttributes): RedirectView {
-        attributes.addFlashAttribute("error", ex.message)
-        return RedirectView("/reset-password")
+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)
     }
-
 }
 ----
 ======