我试图实现一个小服务器的商品商店,但我有一个错误,我做的一切根据教程,所以我不能理解的循环发生在任何方式。也许我的眼睛是模糊的,我看不到日志。我会很高兴的任何提示。为什么他输出的问题,而不是文字谢谢!
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
}
@Basic
private AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
auth.setUserDetailsService(userService);
auth.setPasswordEncoder(passwordEncoder());
return auth;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/product/edit").hasAuthority(Role.ADMIN.name())
// .antMatchers("/product/edit").hasAuthority(Role.ORGANIZACION.name())
// .antMatchers("/order").hasRole(Role.CLIENT.name())
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/auth")
.permitAll()
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/").deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
.and()
.csrf().disable();
}
}
public interface UserService extends UserDetailsService {//security
boolean save(UserDTO userDTO);
}
@Service
public class UserServiceImpl implements UserService{
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
public UserServiceImpl(UserRepository userRepository, PasswordEncoder passwordEncoder) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
}
@Override
public boolean save(UserDTO userDto) {
if(!Objects.equals(userDto.getPassword(), userDto.getMatchingPassword())){
throw new RuntimeException("Password is not equal");
}
User user = User.builder()
.usernames(userDto.getUsername())
.password(passwordEncoder.encode(userDto.getPassword()))
.email(userDto.getEmail())
.role(Role.CLIENT)
.build();
userRepository.save(user);
return true;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findFirstByUsernames(username);
if(user == null){
throw new UsernameNotFoundException("User not found with name: " + username);
}
List<GrantedAuthority> roles = new ArrayList<>();
roles.add(new SimpleGrantedAuthority(user.getRole().name()));
return new org.springframework.security.core.userdetails.User(
user.getUsernames(),
user.getPassword(),
roles);
}
}
错误
org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'securityConfiguration': Requested bean is currently in creation: Is there an unresolvable circular reference?
2023-03-27T01:07:18.156+03:00 ERROR 4484 --- [ restartedMain] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
???????
| securityConfiguration
? ?
| userServiceImpl defined in file [C:\Users\amir1\IdeaProjects\bridge-web\project\TestTask\target\classes\com\example\testtask\service\UserServiceImpl.class]
???????
Action:
Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.
3条答案
按热度按时间nhaq1z211#
你有一个循环依赖,因为Spring不能确定它应该以什么顺序创建你的类。
要创建
SecurityConfiguration
,它需要自动连接一个UserServiceImpl
。但是要创建一个UserServiceImpl
,它需要在SecurityConfiguration
中创建一个PasswordEncoder
。所以你需要打破这种循环依赖。
因此,您要么需要从
UserDetailsImpl
中提取save
函数,并将其放置在一个未自动连接到SecurityConfiguration
的类中。或者在单独的
@Configuration
注解类中提取并创建PasswordEncoder
。gpfsuwkq2#
将
PasswordEncoder
bean移动到另一个配置中。例如:
6tqwzwtp3#
用简单的英语,你告诉spring:
passwordEncoder
,请使用SecurityConfig
并调用其passwordEncoder()
方法SecurityConfig
,请注入UserDetailsService
UserDetailsService
,请注入passwordEncoder
这是一个鸡和蛋的问题:要创建
passwordEncoder
,我们需要SecurityConfig
,它需要UserDetailsService
,它需要passwordEncoder
,这就是我们试图创建的!这个递归永远不会结束!所以你需要切断这个循环,所以让我们检查一下我们是否真的需要这些依赖项:
passwordEncoder
需要SecurityConfig
吗?这听起来很合理。UserDetailsService
需要passwordEncoder
吗?肯定需要。SecurityConfig
是否需要UserDetailsService
?这似乎是不必要的。毕竟,SecurityConfig
中的大多数方法都不需要UserDetailsService
,特别是passwordEncoder()
。您应该只在真正需要
UserDetailsService
的时候才请求它,也就是您要创建authenticationProvider
的时候,而不是每次您想要创建任何在SecurityConfig
中声明的bean的时候。最简单的方法是注入一个
Provider
而不是一个完全初始化的bean,并且只在实际需要时向提供者请求初始化的示例:或者,您可以在JavaConfig中声明
UserService
,而不是通过组件扫描,在这种情况下,工厂方法可以用于查找bean: