Restructure Migration Steps
CLoses gh-12224
This commit is contained in:
@@ -0,0 +1,876 @@
|
||||
= Configuration Migrations
|
||||
|
||||
The following steps relate to changes around how to configure `HttpSecurity`, `WebSecurity`, and `AuthenticationManager`.
|
||||
|
||||
[[use-new-requestmatchers]]
|
||||
== Use the new `requestMatchers` methods
|
||||
|
||||
In Spring Security 5.8, the {security-api-url}org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.html#antMatchers(java.lang.String...)[`antMatchers`], {security-api-url}org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.html#mvcMatchers(java.lang.String...)[`mvcMatchers`], and {security-api-url}org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.html#regexMatchers(java.lang.String...)[`regexMatchers`] methods were deprecated in favor of new xref:servlet/authorization/authorize-http-requests.adoc#_request_matchers[`requestMatchers` methods].
|
||||
|
||||
The new `requestMatchers` methods were added xref:servlet/authorization/authorize-http-requests.adoc[to `authorizeHttpRequests`], `authorizeRequests`, CSRF configuration, `WebSecurityCustomizer` and any other places that had the specialized `RequestMatcher` methods.
|
||||
The deprecated methods are removed in Spring Security 6.
|
||||
|
||||
These new methods have more secure defaults since they choose the most appropriate `RequestMatcher` implementation for your application.
|
||||
In summary, the new methods choose the `MvcRequestMatcher` implementation if your application has Spring MVC in the classpath, falling back to the `AntPathRequestMatcher` implementation if Spring MVC is not present (aligning the behavior with the Kotlin equivalent methods).
|
||||
|
||||
To start using the new methods, you can replace the deprecated methods with the new ones. For example, the following application configuration:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class SecurityConfig {
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeHttpRequests((authz) -> authz
|
||||
.antMatchers("/api/admin/**").hasRole("ADMIN")
|
||||
.antMatchers("/api/user/**").hasRole("USER")
|
||||
.anyRequest().authenticated()
|
||||
);
|
||||
return http.build();
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
can be changed to:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class SecurityConfig {
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeHttpRequests((authz) -> authz
|
||||
.requestMatchers("/api/admin/**").hasRole("ADMIN")
|
||||
.requestMatchers("/api/user/**").hasRole("USER")
|
||||
.anyRequest().authenticated()
|
||||
);
|
||||
return http.build();
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
If you have Spring MVC in the classpath and are using the `mvcMatchers` methods, you can replace it with the new methods and Spring Security will choose the `MvcRequestMatcher` implementation for you.
|
||||
The following configuration:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableWebMvc
|
||||
public class SecurityConfig {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeHttpRequests((authz) -> authz
|
||||
.mvcMatchers("/admin/**").hasRole("ADMIN")
|
||||
.anyRequest().authenticated()
|
||||
);
|
||||
return http.build();
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
is equivalent to:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableWebMvc
|
||||
public class SecurityConfig {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeHttpRequests((authz) -> authz
|
||||
.requestMatchers("/admin/**").hasRole("ADMIN")
|
||||
.anyRequest().authenticated()
|
||||
);
|
||||
return http.build();
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
If you are customizing the `servletPath` property of the `MvcRequestMatcher`, you can now use the `MvcRequestMatcher.Builder` to create `MvcRequestMatcher` instances that share the same servlet path:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableWebMvc
|
||||
public class SecurityConfig {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeHttpRequests((authz) -> authz
|
||||
.mvcMatchers("/admin").servletPath("/path").hasRole("ADMIN")
|
||||
.mvcMatchers("/user").servletPath("/path").hasRole("USER")
|
||||
.anyRequest().authenticated()
|
||||
);
|
||||
return http.build();
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
The code above can be rewritten using the `MvcRequestMatcher.Builder` and the `requestMatchers` method:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableWebMvc
|
||||
public class SecurityConfig {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain securityFilterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector).servletPath("/path");
|
||||
http
|
||||
.authorizeHttpRequests((authz) -> authz
|
||||
.requestMatchers(mvcMatcherBuilder.pattern("/admin")).hasRole("ADMIN")
|
||||
.requestMatchers(mvcMatcherBuilder.pattern("/user")).hasRole("USER")
|
||||
.anyRequest().authenticated()
|
||||
);
|
||||
return http.build();
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
If you are having problem with the new `requestMatchers` methods, you can always switch back to the `RequestMatcher` implementation that you were using.
|
||||
For example, if you still want to use `AntPathRequestMatcher` and `RegexRequestMatcher` implementations, you can use the `requestMatchers` method that accepts a `RequestMatcher` instance:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;
|
||||
import static org.springframework.security.web.util.matcher.RegexRequestMatcher.regexMatcher;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class SecurityConfig {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeHttpRequests((authz) -> authz
|
||||
.requestMatchers(antMatcher("/user/**")).hasRole("USER")
|
||||
.requestMatchers(antMatcher(HttpMethod.POST, "/user/**")).hasRole("ADMIN")
|
||||
.requestMatchers(regexMatcher(".*\\?x=y")).hasRole("SPECIAL") // matches /any/path?x=y
|
||||
.anyRequest().authenticated()
|
||||
);
|
||||
return http.build();
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Note that the above sample uses static factory methods from {security-api-url}org/springframework/security/web/util/matcher/AntPathRequestMatcher.html[`AntPathRequestMatcher`] and {security-api-url}org/springframework/security/web/util/matcher/RegexRequestMatcher.html[`RegexRequestMatcher`] to improve readability.
|
||||
|
||||
If you are using the `WebSecurityCustomizer` interface, you can replace the deprecated `antMatchers` methods:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Bean
|
||||
public WebSecurityCustomizer webSecurityCustomizer() {
|
||||
return (web) -> web.ignoring().antMatchers("/ignore1", "/ignore2");
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
with their `requestMatchers` counterparts:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Bean
|
||||
public WebSecurityCustomizer webSecurityCustomizer() {
|
||||
return (web) -> web.ignoring().requestMatchers("/ignore1", "/ignore2");
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
The same way, if you are customizing the CSRF configuration to ignore some paths, you can replace the deprecated methods with the `requestMatchers` methods:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.csrf((csrf) -> csrf
|
||||
.ignoringAntMatchers("/no-csrf")
|
||||
);
|
||||
return http.build();
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
can be changed to:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.csrf((csrf) -> csrf
|
||||
.ignoringRequestMatchers("/no-csrf")
|
||||
);
|
||||
return http.build();
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
[[use-new-security-matchers]]
|
||||
== Use the new `securityMatchers` methods
|
||||
|
||||
In Spring Security 5.8, the `antMatchers`, `mvcMatchers` and `requestMatchers` methods from `HttpSecurity` were deprecated in favor of new `securityMatchers` methods.
|
||||
|
||||
Note that these methods are not the same from `authorizeHttpRequests` methods <<use-new-requestmatchers,which were deprecated>> in favor of the `requestMatchers` methods.
|
||||
However, the `securityMatchers` methods are similar to the `requestMatchers` methods in the sense that they will choose the most appropriate `RequestMatcher` implementation for your application.
|
||||
In summary, the new methods choose the `MvcRequestMatcher` implementation if your application has Spring MVC in the classpath, falling back to the `AntPathRequestMatcher` implementation if Spring MVC is not present (aligning the behavior with the Kotlin equivalent methods).
|
||||
Another reason for adding the `securityMatchers` methods is to avoid confusion with the `requestMatchers` methods from `authorizeHttpRequests`.
|
||||
|
||||
The following configuration:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.antMatcher("/api/**", "/app/**")
|
||||
.authorizeHttpRequests((authz) -> authz
|
||||
.requestMatchers("/api/admin/**").hasRole("ADMIN")
|
||||
.anyRequest().authenticated()
|
||||
);
|
||||
return http.build();
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
can be rewritten using the `securityMatchers` methods:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.securityMatcher("/api/**", "/app/**")
|
||||
.authorizeHttpRequests((authz) -> authz
|
||||
.requestMatchers("/api/admin/**").hasRole("ADMIN")
|
||||
.anyRequest().authenticated()
|
||||
);
|
||||
return http.build();
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
If you are using a custom `RequestMatcher` in your `HttpSecurity` configuration:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.requestMatcher(new MyCustomRequestMatcher())
|
||||
.authorizeHttpRequests((authz) -> authz
|
||||
.requestMatchers("/api/admin/**").hasRole("ADMIN")
|
||||
.anyRequest().authenticated()
|
||||
);
|
||||
return http.build();
|
||||
}
|
||||
|
||||
public class MyCustomRequestMatcher implements RequestMatcher {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
you can do the same using `securityMatcher`:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.securityMatcher(new MyCustomRequestMatcher())
|
||||
.authorizeHttpRequests((authz) -> authz
|
||||
.requestMatchers("/api/admin/**").hasRole("ADMIN")
|
||||
.anyRequest().authenticated()
|
||||
);
|
||||
return http.build();
|
||||
}
|
||||
|
||||
public class MyCustomRequestMatcher implements RequestMatcher {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
If you are combining multiple `RequestMatcher` implementations in your `HttpSecurity` configuration:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.requestMatchers((matchers) -> matchers
|
||||
.antMatchers("/api/**", "/app/**")
|
||||
.mvcMatchers("/admin/**")
|
||||
.requestMatchers(new MyCustomRequestMatcher())
|
||||
)
|
||||
.authorizeHttpRequests((authz) -> authz
|
||||
.requestMatchers("/admin/**").hasRole("ADMIN")
|
||||
.anyRequest().authenticated()
|
||||
);
|
||||
return http.build();
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
you can change it by using `securityMatchers`:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.securityMatchers((matchers) -> matchers
|
||||
.requestMatchers("/api/**", "/app/**", "/admin/**")
|
||||
.requestMatchers(new MyCustomRequestMatcher())
|
||||
)
|
||||
.authorizeHttpRequests((authz) -> authz
|
||||
.requestMatchers("/admin/**").hasRole("ADMIN")
|
||||
.anyRequest().authenticated()
|
||||
);
|
||||
return http.build();
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
If you are having problems with the `securityMatchers` methods choosing the `RequestMatcher` implementation for you, you can always choose the `RequestMatcher` implementation yourself:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.securityMatcher(antMatcher("/api/**"), antMatcher("/app/**"))
|
||||
.authorizeHttpRequests((authz) -> authz
|
||||
.requestMatchers(antMatcher("/api/admin/**")).hasRole("ADMIN")
|
||||
.anyRequest().authenticated()
|
||||
);
|
||||
return http.build();
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
== Stop Using `WebSecurityConfigurerAdapter`
|
||||
|
||||
=== Publish a `SecurityFilterChain` Bean
|
||||
|
||||
Spring Security 5.4 introduced the capability to publish a `SecurityFilterChain` bean instead of extending `WebSecurityConfigurerAdapter`.
|
||||
In 6.0, `WebSecurityConfigurerAdapter` is removed.
|
||||
To prepare for this change, you can replace constructs like:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeHttpRequests((authorize) -> authorize
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.httpBasic(withDefaults());
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
.Kotlin
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
open class SecurityConfiguration: WebSecurityConfigurerAdapter() {
|
||||
|
||||
@Override
|
||||
override fun configure(val http: HttpSecurity) {
|
||||
http {
|
||||
authorizeHttpRequests {
|
||||
authorize(anyRequest, authenticated)
|
||||
}
|
||||
|
||||
httpBasic {}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
with:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
public class SecurityConfiguration {
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeHttpRequests((authorize) -> authorize
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.httpBasic(withDefaults());
|
||||
return http.build();
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
.Kotlin
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
open class SecurityConfiguration {
|
||||
|
||||
@Bean
|
||||
fun filterChain(http: HttpSecurity): SecurityFilterChain {
|
||||
http {
|
||||
authorizeHttpRequests {
|
||||
authorize(anyRequest, authenticated)
|
||||
}
|
||||
httpBasic {}
|
||||
}
|
||||
return http.build()
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
=== Publish a `WebSecurityCustomizer` Bean
|
||||
|
||||
Spring Security 5.4 https://github.com/spring-projects/spring-security/issues/8978[introduced `WebSecurityCustomizer`] to replace `configure(WebSecurity web)` in `WebSecurityConfigurerAdapter`.
|
||||
To prepare for its removal, you can replace code like the following:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
public void configure(WebSecurity web) {
|
||||
web.ignoring().antMatchers("/ignore1", "/ignore2");
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
.Kotlin
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
open class SecurityConfiguration: WebSecurityConfigurerAdapter() {
|
||||
|
||||
override fun configure(val web: WebSecurity) {
|
||||
web.ignoring().antMatchers("/ignore1", "/ignore2")
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
with:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
public class SecurityConfiguration {
|
||||
|
||||
@Bean
|
||||
public WebSecurityCustomizer webSecurityCustomizer() {
|
||||
return (web) -> web.ignoring().antMatchers("/ignore1", "/ignore2");
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
.Kotlin
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
open class SecurityConfiguration {
|
||||
|
||||
@Bean
|
||||
fun webSecurityCustomizer(): WebSecurityCustomizer {
|
||||
return (web) -> web.ignoring().antMatchers("/ignore1", "/ignore2")
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
=== Publish an `AuthenticationManager` Bean
|
||||
|
||||
As part of `WebSecurityConfigurerAdapeter` removal, `configure(AuthenticationManagerBuilder)` is also removed.
|
||||
Preparing for its removal will differ based on your reason for using it.
|
||||
|
||||
==== LDAP Authentication
|
||||
|
||||
If you are using `auth.ldapAuthentication()` for xref:servlet/authentication/passwords/ldap.adoc[LDAP authentication support], you can replace:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.userDetailsContextMapper(new PersonContextMapper())
|
||||
.userDnPatterns("uid={0},ou=people")
|
||||
.contextSource()
|
||||
.port(0);
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
.Kotlin
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
open class SecurityConfiguration: WebSecurityConfigurerAdapter() {
|
||||
|
||||
override fun configure(auth: AuthenticationManagerBuilder) {
|
||||
auth
|
||||
.ldapAuthentication()
|
||||
.userDetailsContextMapper(PersonContextMapper())
|
||||
.userDnPatterns("uid={0},ou=people")
|
||||
.contextSource()
|
||||
.port(0)
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
with:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
public class SecurityConfiguration {
|
||||
@Bean
|
||||
public EmbeddedLdapServerContextSourceFactoryBean contextSourceFactoryBean() {
|
||||
EmbeddedLdapServerContextSourceFactoryBean contextSourceFactoryBean =
|
||||
EmbeddedLdapServerContextSourceFactoryBean.fromEmbeddedLdapServer();
|
||||
contextSourceFactoryBean.setPort(0);
|
||||
return contextSourceFactoryBean;
|
||||
}
|
||||
|
||||
@Bean
|
||||
AuthenticationManager ldapAuthenticationManager(BaseLdapPathContextSource contextSource) {
|
||||
LdapBindAuthenticationManagerFactory factory =
|
||||
new LdapBindAuthenticationManagerFactory(contextSource);
|
||||
factory.setUserDnPatterns("uid={0},ou=people");
|
||||
factory.setUserDetailsContextMapper(new PersonContextMapper());
|
||||
return factory.createAuthenticationManager();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
.Kotlin
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
open class SecurityConfiguration {
|
||||
@Bean
|
||||
fun contextSourceFactoryBean(): EmbeddedLdapServerContextSourceFactoryBean {
|
||||
val contextSourceFactoryBean: EmbeddedLdapServerContextSourceFactoryBean =
|
||||
EmbeddedLdapServerContextSourceFactoryBean.fromEmbeddedLdapServer()
|
||||
contextSourceFactoryBean.setPort(0)
|
||||
return contextSourceFactoryBean
|
||||
}
|
||||
|
||||
@Bean
|
||||
fun ldapAuthenticationManager(val contextSource: BaseLdapPathContextSource): AuthenticationManager {
|
||||
val factory = LdapBindAuthenticationManagerFactory(contextSource)
|
||||
factory.setUserDnPatterns("uid={0},ou=people")
|
||||
factory.setUserDetailsContextMapper(PersonContextMapper())
|
||||
return factory.createAuthenticationManager()
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
==== JDBC Authentication
|
||||
|
||||
If you are using `auth.jdbcAuthentication()` for xref:servlet/authentication/passwords/jdbc.adoc[JDBC Authentication support], you can replace:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
return new EmbeddedDatabaseBuilder()
|
||||
.setType(EmbeddedDatabaseType.H2)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
UserDetails user = User.withDefaultPasswordEncoder()
|
||||
.username("user")
|
||||
.password("password")
|
||||
.roles("USER")
|
||||
.build();
|
||||
auth.jdbcAuthentication()
|
||||
.withDefaultSchema()
|
||||
.dataSource(this.dataSource)
|
||||
.withUser(user);
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
.Kotlin
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
open class SecurityConfiguration: WebSecurityConfigurerAdapter() {
|
||||
@Bean
|
||||
fun dataSource(): DataSource {
|
||||
return EmbeddedDatabaseBuilder()
|
||||
.setType(EmbeddedDatabaseType.H2)
|
||||
.build()
|
||||
}
|
||||
|
||||
override fun configure(val auth: AuthenticationManagerBuilder) {
|
||||
UserDetails user = User.withDefaultPasswordEncoder()
|
||||
.username("user")
|
||||
.password("password")
|
||||
.roles("USER")
|
||||
.build()
|
||||
auth.jdbcAuthentication()
|
||||
.withDefaultSchema()
|
||||
.dataSource(this.dataSource)
|
||||
.withUser(user)
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
with:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
public class SecurityConfiguration {
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
return new EmbeddedDatabaseBuilder()
|
||||
.setType(EmbeddedDatabaseType.H2)
|
||||
.addScript(JdbcDaoImpl.DEFAULT_USER_SCHEMA_DDL_LOCATION)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public UserDetailsManager users(DataSource dataSource) {
|
||||
UserDetails user = User.withDefaultPasswordEncoder()
|
||||
.username("user")
|
||||
.password("password")
|
||||
.roles("USER")
|
||||
.build();
|
||||
JdbcUserDetailsManager users = new JdbcUserDetailsManager(dataSource);
|
||||
users.createUser(user);
|
||||
return users;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
.Kotlin
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
open class SecurityConfiguration {
|
||||
@Bean
|
||||
fun dataSource(): DataSource {
|
||||
return EmbeddedDatabaseBuilder()
|
||||
.setType(EmbeddedDatabaseType.H2)
|
||||
.addScript(JdbcDaoImpl.DEFAULT_USER_SCHEMA_DDL_LOCATION)
|
||||
.build()
|
||||
}
|
||||
|
||||
@Bean
|
||||
fun users(val dataSource: DataSource): UserDetailsManager {
|
||||
val user = User.withDefaultPasswordEncoder()
|
||||
.username("user")
|
||||
.password("password")
|
||||
.roles("USER")
|
||||
.build()
|
||||
val users = JdbcUserDetailsManager(dataSource)
|
||||
users.createUser(user)
|
||||
return users
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
==== In-Memory Authentication
|
||||
|
||||
If you are using `auth.inMemoryAuthentication()` for xref:servlet/authentication/passwords/in-memory.adoc[In-Memory Authentication support], you can replace:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
UserDetails user = User.withDefaultPasswordEncoder()
|
||||
.username("user")
|
||||
.password("password")
|
||||
.roles("USER")
|
||||
.build();
|
||||
auth.inMemoryAuthentication()
|
||||
.withUser(user);
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
.Kotlin
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
open class SecurityConfiguration: WebSecurityConfigurerAdapter() {
|
||||
override fun configure(val auth: AuthenticationManagerBuilder) {
|
||||
val user = User.withDefaultPasswordEncoder()
|
||||
.username("user")
|
||||
.password("password")
|
||||
.roles("USER")
|
||||
.build()
|
||||
auth.inMemoryAuthentication()
|
||||
.withUser(user)
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
with:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
public class SecurityConfiguration {
|
||||
@Bean
|
||||
public InMemoryUserDetailsManager userDetailsService() {
|
||||
UserDetails user = User.withDefaultPasswordEncoder()
|
||||
.username("user")
|
||||
.password("password")
|
||||
.roles("USER")
|
||||
.build();
|
||||
return new InMemoryUserDetailsManager(user);
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
.Kotlin
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
open class SecurityConfiguration {
|
||||
@Bean
|
||||
fun userDetailsService(): InMemoryUserDetailsManager {
|
||||
UserDetails user = User.withDefaultPasswordEncoder()
|
||||
.username("user")
|
||||
.password("password")
|
||||
.roles("USER")
|
||||
.build()
|
||||
return InMemoryUserDetailsManager(user)
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
==== Other Scenarios
|
||||
|
||||
If you are using `AuthenticationManagerBuilder` for something more sophisticated, you can xref:servlet/authentication/architecture.adoc#servlet-authentication-authenticationmanager[publish your own `AuthenticationManager` `@Bean`] or wire an `AuthenticationManager` instance into the `HttpSecurity` DSL with {security-api-url}org/springframework/security/config/annotation/web/builders/HttpSecurity.html#authenticationManager(org.springframework.security.authentication.AuthenticationManager)[`HttpSecurity#authenticationManager`].
|
||||
Reference in New Issue
Block a user