Reputation: 10790
Below I have a customUserDetailsService
property, and a tokenAuthenticationService
property. I need to pass customUserDetailsService
into tokenAuthenticationService
but tokenAuthenticationService
is a @Bean
file and customUserDetailsService
is a @Service
which means that tokenAuthenticationService
gets called first with parameter for UserDetailsService
as null
for the UserDetailsService
parameter. I need to either delay the initiation of tokenAuthenticationService
as a Bean or Turn tokenAuthenticationService
into a service as well and some how pass those parameters as a constructor. How do I go about doing this ?
package app.config;
import app.repo.User.CustomUserDetailsService;
import app.security.*;
import app.security.filters.StatelessAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.sql.DataSource;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
@Order(2)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private static PasswordEncoder encoder;
@Autowired
private TokenAuthenticationService tokenAuthenticationService;
@Autowired
private UserDetailsService customUserDetailsService;
@Autowired
private RESTAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
private RESTAuthenticationFailureHandler authenticationFailureHandler;
@Autowired
private RESTAuthenticationSuccessHandler authenticationSuccessHandler;
public WebSecurityConfig() {
super(true);
}
@Autowired
public void configureAuth(AuthenticationManagerBuilder auth,DataSource dataSource) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").authenticated();
http.csrf().disable();
http.httpBasic();
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);
http.formLogin().defaultSuccessUrl("/").successHandler(authenticationSuccessHandler);
http.formLogin().failureHandler(authenticationFailureHandler);
http.addFilterBefore(new StatelessAuthenticationFilter(tokenAuthenticationService),
UsernamePasswordAuthenticationFilter.class);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService);
}
@Bean
public TokenAuthenticationService tokenAuthenticationService() {
tokenAuthenticationService = new TokenAuthenticationService("tooManySecrets", customUserDetailsService);
return tokenAuthenticationService;
}
}
Upvotes: 0
Views: 3421
Reputation: 44555
You can define the userDetailsService as direct dependency of the TokenAuthenticationService like this:
@Bean
public TokenAuthenticationService tokenAuthenticationService(UserDetailsService userDetailsService) {
tokenAuthenticationService = new TokenAuthenticationService("tooManySecrets", userDetailsService);
return tokenAuthenticationService;
}
That way, Spring will make sure, that the UserDetailsService is instantiated and injected when the TokenAuthenticationService is created.
Upvotes: 1
Reputation: 4214
You can try annotating tokenAuthenticationService() with @Lazy. Though even if that worked its a bit unpredictable, and future modifications to this or related beans may leave you wondering on why it stopped working.
Best to declare TokenAuthenticationService
as @Service
& inject UserDetailsService
in it.
As a side note its better to not mix @Configuration with application code to avoid these kind of issues.
Update - I don't think @Lazy is going to work here. Since you are relying on @Bean being invoked in the middle of @Autowired beans being processed.
In order for your code to work the @Autowired
customUserDetailsService should be set first, then @Bean
method called and then @Autowired
tokenAuthenticationService should be set.
Upvotes: 0