From e86dac8a647c1bf9e6f30fea25fbe3de15b4fab4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2024 03:46:00 +0000 Subject: [PATCH 1/3] Bump io.projectreactor:reactor-bom from 2023.0.9 to 2023.0.10 Bumps [io.projectreactor:reactor-bom](https://github.com/reactor/reactor) from 2023.0.9 to 2023.0.10. - [Release notes](https://github.com/reactor/reactor/releases) - [Commits](https://github.com/reactor/reactor/compare/2023.0.9...2023.0.10) --- updated-dependencies: - dependency-name: io.projectreactor:reactor-bom dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 74288d7713..655f13c573 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -28,7 +28,7 @@ com-unboundid-unboundid-ldapsdk = "com.unboundid:unboundid-ldapsdk:6.0.11" commons-collections = "commons-collections:commons-collections:3.2.2" io-micrometer-micrometer-observation = "io.micrometer:micrometer-observation:1.12.10" io-mockk = "io.mockk:mockk:1.13.12" -io-projectreactor-reactor-bom = "io.projectreactor:reactor-bom:2023.0.9" +io-projectreactor-reactor-bom = "io.projectreactor:reactor-bom:2023.0.10" io-rsocket-rsocket-bom = { module = "io.rsocket:rsocket-bom", version.ref = "io-rsocket" } io-spring-javaformat-spring-javaformat-checkstyle = { module = "io.spring.javaformat:spring-javaformat-checkstyle", version.ref = "io-spring-javaformat" } io-spring-javaformat-spring-javaformat-gradle-plugin = { module = "io.spring.javaformat:spring-javaformat-gradle-plugin", version.ref = "io-spring-javaformat" } From f3061d9c1ac6031198e56a10f2bc5d0dd32993f5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Sep 2024 03:31:49 +0000 Subject: [PATCH 2/3] Bump org.springframework:spring-framework-bom from 6.1.12 to 6.1.13 Bumps [org.springframework:spring-framework-bom](https://github.com/spring-projects/spring-framework) from 6.1.12 to 6.1.13. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.12...v6.1.13) --- updated-dependencies: - dependency-name: org.springframework:spring-framework-bom dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 655f13c573..4eee28bb67 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ org-jetbrains-kotlin = "1.9.25" org-jetbrains-kotlinx = "1.7.3" org-mockito = "5.5.0" org-opensaml = "4.3.2" -org-springframework = "6.1.12" +org-springframework = "6.1.13" [libraries] ch-qos-logback-logback-classic = "ch.qos.logback:logback-classic:1.4.14" From 0a4eb0f09afbf0e76b4693f8110f0c0fde58be8b Mon Sep 17 00:00:00 2001 From: Steve Riesenberg <5248162+sjohnr@users.noreply.github.com> Date: Fri, 13 Sep 2024 16:06:01 -0500 Subject: [PATCH 3/3] Update credential erasure examples Closes gh-15683 --- .../authentication/passwords/index.adoc | 290 +++++++++--------- 1 file changed, 140 insertions(+), 150 deletions(-) diff --git a/docs/modules/ROOT/pages/servlet/authentication/passwords/index.adoc b/docs/modules/ROOT/pages/servlet/authentication/passwords/index.adoc index ff6cf854d0..386bf7f4f4 100644 --- a/docs/modules/ROOT/pages/servlet/authentication/passwords/index.adoc +++ b/docs/modules/ROOT/pages/servlet/authentication/passwords/index.adoc @@ -326,156 +326,7 @@ 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: - -.Publish `AuthenticationManager` bean for Spring Security -[tabs] -===== -Java:: -+ -[source,java,role="primary"] ----- -@Configuration -@EnableWebSecurity -public class SecurityConfig { - - @Bean - public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { - http - .authorizeHttpRequests((authorize) -> authorize - .requestMatchers("/login").permitAll() - .anyRequest().authenticated() - ) - .httpBasic(Customizer.withDefaults()) - .formLogin(Customizer.withDefaults()); - - return http.build(); - } - - @Bean - public AuthenticationManager authenticationManager( - UserDetailsService userDetailsService, - PasswordEncoder passwordEncoder) { - DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(); - authenticationProvider.setUserDetailsService(userDetailsService); - authenticationProvider.setPasswordEncoder(passwordEncoder); - - ProviderManager providerManager = new ProviderManager(authenticationProvider); - providerManager.setEraseCredentialsAfterAuthentication(false); - - return providerManager; - } - - @Bean - public UserDetailsService userDetailsService() { - UserDetails userDetails = User.withDefaultPasswordEncoder() - .username("user") - .password("password") - .roles("USER") - .build(); - - return new InMemoryUserDetailsManager(userDetails); - } - - @Bean - public PasswordEncoder passwordEncoder() { - return PasswordEncoderFactories.createDelegatingPasswordEncoder(); - } - -} ----- - -XML:: -+ -[source,xml,role="secondary"] ----- - - - - - - - - - - - - - - - - - - - - - ----- - -Kotlin:: -+ -[source,kotlin,role="secondary"] ----- -import org.springframework.security.config.annotation.web.invoke - -@Configuration -@EnableWebSecurity -class SecurityConfig { - - @Bean - fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { - http { - authorizeHttpRequests { - authorize("/login", permitAll) - authorize(anyRequest, authenticated) - } - formLogin { } - httpBasic { } - } - - return http.build() - } - - @Bean - fun authenticationManager( - userDetailsService: UserDetailsService, - passwordEncoder: PasswordEncoder): AuthenticationManager { - val authenticationProvider = DaoAuthenticationProvider() - authenticationProvider.setUserDetailsService(userDetailsService) - authenticationProvider.setPasswordEncoder(passwordEncoder) - - val providerManager = ProviderManager(authenticationProvider) - providerManager.eraseCredentialsAfterAuthentication = false - - return providerManager - } - - @Bean - fun userDetailsService(): UserDetailsService { - val user = User.withDefaultPasswordEncoder() - .username("user") - .password("password") - .roles("USER") - .build() - - return InMemoryUserDetailsManager(user) - } - - @Bean - fun passwordEncoder(): PasswordEncoder { - return PasswordEncoderFactories.createDelegatingPasswordEncoder() - } - -} ----- -===== - -Alternatively, you can take advantage of the fact that the `AuthenticationManagerBuilder` used to build Spring Security's global `AuthenticationManager` is published as a bean. +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` @@ -539,3 +390,142 @@ class SecurityConfig { } ---- ===== + +Alternatively, you may configure a local `AuthenticationManager` to override the global one. + +.Configure local `AuthenticationManager` for Spring Security +[tabs] +===== +Java:: ++ +[source,java,role="primary"] +---- +@Configuration +@EnableWebSecurity +public class SecurityConfig { + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .authorizeHttpRequests((authorize) -> authorize + .anyRequest().authenticated() + ) + .httpBasic(Customizer.withDefaults()) + .formLogin(Customizer.withDefaults()) + .authenticationManager(authenticationManager()); + + return http.build(); + } + + private AuthenticationManager authenticationManager() { + DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(); + authenticationProvider.setUserDetailsService(userDetailsService()); + authenticationProvider.setPasswordEncoder(passwordEncoder()); + + ProviderManager providerManager = new ProviderManager(authenticationProvider); + providerManager.setEraseCredentialsAfterAuthentication(false); + + return providerManager; + } + + private UserDetailsService userDetailsService() { + UserDetails userDetails = User.withDefaultPasswordEncoder() + .username("user") + .password("password") + .roles("USER") + .build(); + + return new InMemoryUserDetailsManager(userDetails); + } + + private PasswordEncoder passwordEncoder() { + return PasswordEncoderFactories.createDelegatingPasswordEncoder(); + } + +} +---- + +XML:: ++ +[source,xml,role="secondary"] +---- + + + + + + + + + + + + + + + + + + + + +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +import org.springframework.security.config.annotation.web.invoke + +@Configuration +@EnableWebSecurity +class SecurityConfig { + + @Bean + fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { + http { + authorizeHttpRequests { + authorize(anyRequest, authenticated) + } + formLogin { } + httpBasic { } + authenticationManager = authenticationManager() + } + + return http.build() + } + + @Bean + fun authenticationManager(): AuthenticationManager { + val authenticationProvider = DaoAuthenticationProvider() + authenticationProvider.setUserDetailsService(userDetailsService()) + authenticationProvider.setPasswordEncoder(passwordEncoder()) + + val providerManager = ProviderManager(authenticationProvider) + providerManager.eraseCredentialsAfterAuthentication = false + + return providerManager + } + + private fun userDetailsService(): UserDetailsService { + val user = User.withDefaultPasswordEncoder() + .username("user") + .password("password") + .roles("USER") + .build() + + return InMemoryUserDetailsManager(user) + } + + private fun passwordEncoder(): PasswordEncoder { + return PasswordEncoderFactories.createDelegatingPasswordEncoder() + } + +} +---- +===== +