A Spring Security configuration class defines the configuration for restricting access to a spring web service only to authenticated and authorized users.
In Spring Boot 2.6 and earlier versions this was done via extending the WebSecurityConfigurerAdapter class and overriding abstract methods like
protected void configure(AuthenticationManagerBuilder auth) {…}
public void configure(WebSecurity web) throws Exception {…}
and embedding them in a spring security config class like this:
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.mvcMatchers(HttpMethod.GET, "/books/**").hasAnyRole("USER", "ADMIN")
.mvcMatchers("/**").authenticated()
.and()
.httpBasic()
.and()
.csrf().disable();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
…
}
}
The new Spring Security configuration class, starting with Spring Boot 2.7 does not extend the WebSecurityConfigurerAdapter class anymore.
In this @Configuration class the principal method is @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception where the Spring Security filter chain is told which requests to filter. Several authentication schemes defined in separate beans can be added to the http.authorizeHttpRequests builder chain:
@EnableMethodSecurity
@Configuration
@Import(PasswordConfig.class)
public class MySecurityConfig {
@Autowired
private CustomUserDetailsService customUserDetailsService;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private CustomAuthenticationProvider customAuthenticationProvider;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((authz) -> authz
.requestMatchers(HttpMethod.GET, "/books").hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated())
.httpBasic(withDefaults())
.userDetailsService(userDetailsService(passwordEncoder))
.userDetailsService(customUserDetailsService)
.authenticationProvider(customAuthenticationProvider)
.csrf(CsrfConfigurer::disable);
return http.build();
}
@Bean public InMemoryUserDetailsManager userDetailsService(PasswordEncoder passwordEncoder) {
...
return new InMemoryUserDetailsManager(user, admin);
}
}
A small final point: Place the PasswordEncoder @Bean in a separate configuration (defined in @Import(PasswordConfig.class)) as embedding this dependency as @Bean in the SecurityConfig runs into circular dependency issues!
@Configuration
public class PasswordConfig {
@Bean public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
}
Recent Comments