我正在使用 Spring Security 开发 Spring Boot 应用程序,并且在 AppConfig.java 文件中遇到了依赖项注入问题。除非我在构造函数中使用 @Lazy 注释,否则应用程序将不会启动。我宁愿避免使用 @Lazy,但在尝试配置没有它的安全性时,我遇到了循环引用错误。
这是我当前的 AppConfig.java:
@Configuration
@EnableWebSecurity
public class AppConfig extends WebSecurityConfigurerAdapter {
private final CurrentUserService currentUserService;
private final SessionFilter sessionFilter;
private final PasswordEncoder passwordEncoder;
@Autowired
@Lazy
public AppConfig(CurrentUserService currentUserService, SessionFilter sessionFilter, PasswordEncoder passwordEncoder) {
this.currentUserService = currentUserService;
this.sessionFilter = sessionFilter;
this.passwordEncoder = passwordEncoder;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(currentUserService).passwordEncoder(passwordEncoder);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http = http.cors().and().csrf().disable();
http = http.exceptionHandling().authenticationEntryPoint(
(request, response, authException) -> {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
}
).and();
http.authorizeRequests().antMatchers("/api/login").permitAll().anyRequest().authenticated();
http.addFilterBefore(sessionFilter, UsernamePasswordAuthenticationFilter.class);
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
问题:
如果我删除@Lazy,应用程序将无法启动并抛出以下错误:
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'appConfig' defined in file [C:\path\to\AppConfig.class]: Unsatisfied dependency expressed through constructor parameter 2; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'appConfig': Requested bean is currently in creation: Is there an unresolvable circular reference?
我尝试切换到字段注入以避免构造函数注入,如下所示:
@Autowired
private CurrentUserService currentUserService;
@Autowired
private SessionFilter sessionFilter;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(currentUserService).passwordEncoder(passwordEncoder);
}
但是我遇到了类似的错误:
Error creating bean with name 'appConfig': Unsatisfied dependency expressed through field 'passwordEncoder'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'appConfig': Requested bean is currently in creation: Is there an unresolvable circular reference?
我的问题:
How can I resolve this circular dependency without relying on @Lazy?
Is there a better approach for injecting these dependencies in a Spring Security configuration?
Are there specific patterns or workarounds for avoiding circular references in Spring Boot security setups?
任何建议或见解将不胜感激!
发生此错误是因为您在注入它的同一类中创建
PasswordEncoder
。
最好的解决方案是根本不自动连接
PasswordEncoder
(或 CurrentUserService
)。
看来这些实例仅在
configure(AuthenticationManagerBuilder auth)
方法中使用,这是多余的。
将
PasswordEncoder
和 UserDetailsService
注册为 bean 就足以让 Spring Security 检测到它们并在您的配置中使用它们。
换句话说,您应该删除以下代码:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(currentUserService).passwordEncoder(passwordEncoder);
}
应用程序仍将以完全相同的方式运行。