我遇到了一个循环依赖错误问题。当我在securityConfig类中定义UserDetailsService bean时,会抛出这个错误,但是如果我在authenticationConfig类中定义了同一个bean,错误就消失了,我不知道为什么。这是代码。
@Configuration
public class SecurityConfig {
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
@Autowired
private InitialAuthenticationFilter initialAuthenticationFilter;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http.csrf().disable()
.httpBasic().and()
.addFilterBefore(initialAuthenticationFilter, BasicAuthenticationFilter.class)
.addFilterAfter(jwtAuthenticationFilter,BasicAuthenticationFilter.class)
.authorizeHttpRequests().requestMatchers("/actuator/**").permitAll().and()
.authorizeHttpRequests().anyRequest().authenticated()
.and()
.build();
}
@Bean
public UserDetailsService userDetailsService(){
UserDetails user = User.builder()
.username("user")
.password("123")
.roles("USER")
.build();
UserDetails admin = User.builder()
.username("admin")
.password("123")
.roles("USER", "ADMIN")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
}
@Configuration
public class AuthenticationConfig {
@Autowired
private OtpAuthenticationProvider otpAuthenticationProvider;
@Autowired
private UsernamePasswordAuthenticationProvider usernamePasswordAuthenticationProvider;
@Bean
public AuthenticationManager authManager(HttpSecurity http) throws Exception {
AuthenticationManagerBuilder authenticationManagerBuilder =
http.getSharedObject(AuthenticationManagerBuilder.class);
authenticationManagerBuilder.authenticationProvider(usernamePasswordAuthenticationProvider).authenticationProvider(otpAuthenticationProvider);
return authenticationManagerBuilder.build();
}
}
@Component
public class InitialAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private AuthenticationManager manager;
@Value("${jwt.signing.key}")
private String signingKey;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException { // do filtering
}
}
// and then i have some providers like this one
@Component
public class UsernamePasswordAuthenticationProvider implements AuthenticationProvider{
@Autowired
private AuthenticationServerProxy proxy;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = String.valueOf(authentication.getCredentials());
proxy.sendAuth(username, password);
return new UsernamePasswordAuthenticationToken(username, password);
}
@Override
public boolean supports(Class<?> authentication) {
// TODO Auto-generated method stub
return UsernamePasswordAuthentication.class.isAssignableFrom(authentication);
}
}
这是日志:
Exception: org.springframework.beans.factory.UnsatisfiedDependencyException.
Message: Error creating bean with name 'securityConfig': Unsatisfied dependency expressed through field 'initialAuthenticationFilter':
Error creating bean with name 'initialAuthenticationFilter': Unsatisfied dependency expressed through field 'manager':
Error creating bean with name 'authManager' defined in class path resource [root/AuthenticationConfig.class]:
Unsatisfied dependency expressed through method 'authManager' parameter 0:
Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.httpSecurity'
defined in class path resource [org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.class]:
Failed to instantiate [org.springframework.security.config.annotation.web.builders.HttpSecurity]:
Factory method 'httpSecurity' threw exception with message: Error creating bean with name 'securityConfig':
Requested bean is currently in creation: Is there an unresolvable circular reference?
然后是这个图:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| securityConfig (field private root.filters.InitialAuthenticationFilter root.SecurityConfig.initialAuthenticationFilter)
↑ ↓
| initialAuthenticationFilter (field private org.springframework.security.authentication.AuthenticationManager root.filters.InitialAuthenticationFilter.manager)
↑ ↓
| authManager defined in class path resource [root/AuthenticationConfig.class]
↑ ↓
| org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.httpSecurity defined in class path resource [org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.class]
└─────┘
如果我将UserDetailsService bean移动到另一个类,一切都工作得很好,但我试图理解循环依赖性来自何处。日志显示authManager依赖于HttpSecurity,这是正确的,但HttpSecurity依赖于securityConfig,我试图用调试器检查HttpSecurity bean,但找不到任何依赖性
1条答案
按热度按时间lf5gs5x21#
我检查了
UserDetailsService
与HttpSecurity
没有任何直接关系。但是你必须使用UserDetailsService
来定义HttpSecurity
中的角色。你在Spring API HttpSecurity中有信息。循环依赖应该与
AuthenticationManager
的HttpSecurity
相关。在旧版spring中,您创建了AuthenticationManager
,覆盖了WebSecurityConfigurerAdapter
。代码如下:但是在最后的版本中,你可以使用
filterChain
,在你的例子中是securityFilerChange
,来示例化AuthenticationManager
。bean可能是这样的:在这个实现中,您只有一个站点使用HttpSecurity,循环依赖错误应该消失。
您可以查看有关如何使用此
AuthenticationManager
的更多信息,在此link中了解如何升级WebSecurityConfigurerAdapter
。