diff --git a/docs/modules/ROOT/pages/servlet/authentication/passwords/index.adoc b/docs/modules/ROOT/pages/servlet/authentication/passwords/index.adoc index b40920cbb7..b13cdb615d 100644 --- a/docs/modules/ROOT/pages/servlet/authentication/passwords/index.adoc +++ b/docs/modules/ROOT/pages/servlet/authentication/passwords/index.adoc @@ -326,10 +326,74 @@ Normally, Spring Security builds an `AuthenticationManager` internally composed In certain cases, it may still be desired to customize the instance of `AuthenticationManager` used by Spring Security. For example, you may need to simply disable xref:servlet/authentication/architecture.adoc#servlet-authentication-providermanager-erasing-credentials[credential erasure] for cached users. -The recommended way to do this is to simply publish your own `AuthenticationManager` bean, and Spring Security will use it. -You can publish an `AuthenticationManager` using the following configuration: +To do this, you can take advantage of the fact that the `AuthenticationManagerBuilder` used to build Spring Security's global `AuthenticationManager` is published as a bean. +You can configure the builder as follows: + +.Configure global `AuthenticationManagerBuilder` +[tabs] +===== +Java:: ++ +[source,java,role="primary"] +---- +@Configuration +@EnableWebSecurity +public class SecurityConfig { + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + // ... + return http.build(); + } + + @Bean + public UserDetailsService userDetailsService() { + // Return a UserDetailsService that caches users + // ... + } + + @Autowired + public void configure(AuthenticationManagerBuilder builder) { + builder.eraseCredentials(false); + } + +} +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +import org.springframework.security.config.annotation.web.invoke -.Publish `AuthenticationManager` bean for Spring Security +@Configuration +@EnableWebSecurity +class SecurityConfig { + + @Bean + fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { + // ... + return http.build() + } + + @Bean + fun userDetailsService(): UserDetailsService { + // Return a UserDetailsService that caches users + // ... + } + + @Autowired + fun configure(builder: AuthenticationManagerBuilder) { + builder.eraseCredentials(false) + } + +} +---- +===== + +Alternatively, you may configure a local `AuthenticationManager` to override the global one. + +.Configure local `AuthenticationManager` for Spring Security [tabs] ===== Java:: @@ -344,22 +408,19 @@ public class SecurityConfig { public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests((authorize) -> authorize - .requestMatchers("/login").permitAll() .anyRequest().authenticated() ) .httpBasic(Customizer.withDefaults()) - .formLogin(Customizer.withDefaults()); + .formLogin(Customizer.withDefaults()) + .authenticationManager(authenticationManager()); return http.build(); } - @Bean - public AuthenticationManager authenticationManager( - UserDetailsService userDetailsService, - PasswordEncoder passwordEncoder) { + private AuthenticationManager authenticationManager() { DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(); - authenticationProvider.setUserDetailsService(userDetailsService); - authenticationProvider.setPasswordEncoder(passwordEncoder); + authenticationProvider.setUserDetailsService(userDetailsService()); + authenticationProvider.setPasswordEncoder(passwordEncoder()); ProviderManager providerManager = new ProviderManager(authenticationProvider); providerManager.setEraseCredentialsAfterAuthentication(false); @@ -367,8 +428,7 @@ public class SecurityConfig { return providerManager; } - @Bean - public UserDetailsService userDetailsService() { + private UserDetailsService userDetailsService() { UserDetails userDetails = User.withDefaultPasswordEncoder() .username("user") .password("password") @@ -378,8 +438,7 @@ public class SecurityConfig { return new InMemoryUserDetailsManager(userDetails); } - @Bean - public PasswordEncoder passwordEncoder() { + private PasswordEncoder passwordEncoder() { return PasswordEncoderFactories.createDelegatingPasswordEncoder(); } @@ -390,8 +449,7 @@ XML:: + [source,xml,role="secondary"] ---- - - + @@ -431,23 +489,21 @@ class SecurityConfig { fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { http { authorizeHttpRequests { - authorize("/login", permitAll) authorize(anyRequest, authenticated) } formLogin { } httpBasic { } + authenticationManager = authenticationManager() } return http.build() } @Bean - fun authenticationManager( - userDetailsService: UserDetailsService, - passwordEncoder: PasswordEncoder): AuthenticationManager { + fun authenticationManager(): AuthenticationManager { val authenticationProvider = DaoAuthenticationProvider() - authenticationProvider.setUserDetailsService(userDetailsService) - authenticationProvider.setPasswordEncoder(passwordEncoder) + authenticationProvider.setUserDetailsService(userDetailsService()) + authenticationProvider.setPasswordEncoder(passwordEncoder()) val providerManager = ProviderManager(authenticationProvider) providerManager.eraseCredentialsAfterAuthentication = false @@ -455,8 +511,7 @@ class SecurityConfig { return providerManager } - @Bean - fun userDetailsService(): UserDetailsService { + private fun userDetailsService(): UserDetailsService { val user = User.withDefaultPasswordEncoder() .username("user") .password("password") @@ -466,8 +521,7 @@ class SecurityConfig { return InMemoryUserDetailsManager(user) } - @Bean - fun passwordEncoder(): PasswordEncoder { + private fun passwordEncoder(): PasswordEncoder { return PasswordEncoderFactories.createDelegatingPasswordEncoder() } @@ -475,67 +529,3 @@ class SecurityConfig { ---- ===== -Alternatively, you can take advantage of the fact that the `AuthenticationManagerBuilder` used to build Spring Security's global `AuthenticationManager` is published as a bean. -You can configure the builder as follows: - -.Configure global `AuthenticationManagerBuilder` -[tabs] -===== -Java:: -+ -[source,java,role="primary"] ----- -@Configuration -@EnableWebSecurity -public class SecurityConfig { - - @Bean - public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { - // ... - return http.build(); - } - - @Bean - public UserDetailsService userDetailsService() { - // Return a UserDetailsService that caches users - // ... - } - - @Autowired - public void configure(AuthenticationManagerBuilder builder) { - builder.eraseCredentials(false); - } - -} ----- - -Kotlin:: -+ -[source,kotlin,role="secondary"] ----- -import org.springframework.security.config.annotation.web.invoke - -@Configuration -@EnableWebSecurity -class SecurityConfig { - - @Bean - fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { - // ... - return http.build() - } - - @Bean - fun userDetailsService(): UserDetailsService { - // Return a UserDetailsService that caches users - // ... - } - - @Autowired - fun configure(builder: AuthenticationManagerBuilder) { - builder.eraseCredentials(false) - } - -} ----- -=====