I got error while running this code, there is an injection cycle in the code but I cannot find it. btw, I'm new with Spring. How can I solve this problem? And any good documentation about it ?
Here is my code;
WebSecurityConfiguration class:
package com.trendyol.app;
import com.trendyol.app.auth.JwtTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
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.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true) //Tüm methodlarımızdan önce security devreye girer
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
///////////////////
@Autowired
private JwtTokenFilter jwtTokenFilter;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
public void configurePasswordEncoder(AuthenticationManagerBuilder builder ) throws Exception{
builder.userDetailsService(userDetailsService).passwordEncoder(getBCryptPasswordEncoder());
}
///////////////////
@Bean
public BCryptPasswordEncoder getBCryptPasswordEncoder(){
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationManager getAuthenticationManager() throws Exception{
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/login") //bu adress hariç
.authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class);
}
}
UserDetailsService:
package com.trendyol.app.auth;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
@Service
public class UserDetailsService implements org.springframework.security.core.userdetails.UserDetailsService {
private Map<String,String > users=new HashMap<>();
@Autowired
private BCryptPasswordEncoder passwordEncoder;
@PostConstruct
public void init(){
users.put("temelt", passwordEncoder.encode("123"));
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if(users.containsKey(username)){
return new User(username,users.get(username),new ArrayList<>());
}
throw new UsernameNotFoundException(username);
}
}
LOGs: Description:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐ | webSecurityConfiguration (field private org.springframework.security.core.userdetails.UserDetailsService com.trendyol.app.WebSecurityConfiguration.userDetailsService) ↑ ↓ | userDetailsService (field private org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder com.trendyol.app.auth.UserDetailsService.passwordEncoder) └─────┘
UserDetailsService
, which in turn needs aPasswordEncoder
which is created by the configuration. Hence a cycle.UserDetailsService
to use aPasswordEncoder
(the interface) instead of the concrete implementation (this won't solve it but is better).