Reputation: 455
I am trying to update to Spring Boot 2.7.0-SNAPSHOT. WebSecurityConfigurerAdapter is deprecated in this version.
Old WebSecurityConfig with WebSecurityConfigurerAdapter (working fine):
/**
* SecurityConfig
*
*/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;
@Autowired
private CustomAuthenticationFailureHandler customAuthenticationFailureHandler;
@Autowired
private OAuth2AuthenticationSuccessHandler oAuth2AuthenticationSuccessHandler;
@Autowired
private OAuth2AuthenticationFailureHandler oAuth2AuthenticationFailureHandler;
@Autowired
private OAuth2UserServiceImpl oAuth2UserServiceImpl;
/**
* for development
*
* @return
*/
@Bean
public PasswordEncoder passwordEncoder() {
// for development
return NoOpPasswordEncoder.getInstance();
}
@Override
public void configure(WebSecurity web) {
// ignoring
web.ignoring().antMatchers("/css/**", "/js/**", "/img/**", "/lib/**", "/favicon.ico", "/oauth2");
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/", "/login", "/error", "/message/**").permitAll();
http.authorizeRequests().anyRequest().authenticated();
http.formLogin();
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint("/login"));
http.addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class);
// OAuth2
http.oauth2Login().loginPage("/").defaultSuccessUrl("/home", false);
http.oauth2Login().userInfoEndpoint().userService(oAuth2UserServiceImpl);
http.oauth2Login().successHandler(oAuth2AuthenticationSuccessHandler);
http.oauth2Login().failureHandler(oAuth2AuthenticationFailureHandler);
http.logout().logoutUrl("/logout").logoutSuccessUrl("/login").deleteCookies("JSESSIONID");
http.csrf().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.enableSessionUrlRewriting(false);
}
private MyAuthenticationFilter authenticationFilter() throws Exception {
MyAuthenticationFilter filter = new MyAuthenticationFilter();
filter.setAuthenticationManager(authenticationManagerBean());
filter.setAuthenticationSuccessHandler(customAuthenticationSuccessHandler);
filter.setAuthenticationFailureHandler(customAuthenticationFailureHandler);
filter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/authentication", "POST"));
return filter;
}
private AuthenticationEntryPoint authenticationEntryPoint(String loginFormUrl) {
return new MyLoginUrlAuthenticationEntryPoint(loginFormUrl);
}
}
After reading this blog post, I have modified the new WebSecurityConfig:
/**
* SecurityConfig
*
*/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
@Autowired
private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;
@Autowired
private CustomAuthenticationFailureHandler customAuthenticationFailureHandler;
@Autowired
private OAuth2AuthenticationSuccessHandler oAuth2AuthenticationSuccessHandler;
@Autowired
private OAuth2AuthenticationFailureHandler oAuth2AuthenticationFailureHandler;
@Autowired
private OAuth2UserServiceImpl oAuth2UserServiceImpl;
/**
* for development
*
* @return
*/
@Bean
public PasswordEncoder passwordEncoder() {
// for development
return NoOpPasswordEncoder.getInstance();
}
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring().antMatchers(
"/css/**", "/js/**", "/img/**", "/lib/**", "/favicon.ico", "/oauth2");
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/", "/login", "/error", "/message/**").permitAll();
http.authorizeRequests().anyRequest().authenticated();
http.formLogin();
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint("/login"));
http.addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class);
// OAuth2
http.oauth2Login().loginPage("/").defaultSuccessUrl("/home", false);
http.oauth2Login().userInfoEndpoint().userService(oAuth2UserServiceImpl);
http.oauth2Login().successHandler(oAuth2AuthenticationSuccessHandler);
http.oauth2Login().failureHandler(oAuth2AuthenticationFailureHandler);
http.logout().logoutUrl("/logout").logoutSuccessUrl("/login").deleteCookies("JSESSIONID");
http.csrf().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.enableSessionUrlRewriting(false);
return http.build();
}
private MyAuthenticationFilter authenticationFilter() throws Exception {
MyAuthenticationFilter filter = new MyAuthenticationFilter();
// How can I fix this? ------------------------------------------
filter.setAuthenticationManager(authenticationManagerBean());
// --------------------------------------------------------------
filter.setAuthenticationSuccessHandler(customAuthenticationSuccessHandler);
filter.setAuthenticationFailureHandler(customAuthenticationFailureHandler);
filter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/authentication", "POST"));
return filter;
}
private AuthenticationEntryPoint authenticationEntryPoint(String loginFormUrl) {
return new MyLoginUrlAuthenticationEntryPoint(loginFormUrl);
}
}
I was able to fix two methods. (#configure(WebSecurity web) and #configure(HttpSecurity http))
However, I can't figure out how to fix authenticationManagerBean(). Where do I get the AuthenticationManager from?
Upvotes: 15
Views: 16625
Reputation: 181
Here's the entire class that took me day to configure. Hope it could save your time.
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class ApplicationSecurityConfig {
private final UserDetailsService userService;
private final AuthenticationConfiguration configuration;
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
AbstractAuthenticationProcessingFilter filter = new CustomizedAuthenticationFilter(authenticationManager());
filter.setFilterProcessesUrl("/api/login");
http.csrf().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.authorizeRequests().antMatchers(HttpMethod.POST, "/api/login").permitAll();
http.authorizeRequests().anyRequest().authenticated();
http.addFilter(filter);
return http.build();
}
@Bean
AuthenticationManager authenticationManager() throws Exception {
return configuration.getAuthenticationManager();
}
@Autowired
void configure(AuthenticationManagerBuilder builder) throws Exception {
builder.userDetailsService(userService).passwordEncoder(new BCryptPasswordEncoder());
}
}
Upvotes: 9
Reputation: 294
If you want to inject AuthenticationManager into other spring components, you can use the following configuration.
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
This approach has solved the problem for me and you can inject AuthenticationManager wherever you need.
EDIT:
@EnableWebSecurity
@RequiredArgsConstructor
public class SpringSecurityConfiguration {
private final AuthenticationConfiguration authenticationConfiguration;
@Bean
public AuthenticationManager authenticationManager() throws Exception
{
return authenticationConfiguration.getAuthenticationManager();
}
Upvotes: 1
Reputation: 6479
You can create a custom DSL. This is actually how Spring Security works internally.
public class MyCustomDsl extends AbstractHttpConfigurer<MyCustomDsl, HttpSecurity> {
@Override
public void configure(HttpSecurity http) throws Exception {
AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class);
http.addFilterBefore(new MyAuthenticationFilter(authenticationManager), UsernamePasswordAuthenticationFilter.class);
}
public static MyCustomDsl customDsl() {
return new MyCustomDsl();
}
}
Then you can apply the custom DSL when building the SecurityFilterChain
:
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// ...
http.apply(customDsl());
return http.build();
}
Upvotes: 4