引起:org.springframework.beans.factory.BeanCreationException:创建文件 [mypath\security ilter\AuthenticationFilter.class] 中定义的名为“authenticationFilter”的 bean 时出错:必须指定authenticationManager
.
.
原因:java.lang.IllegalArgumentException:必须指定authenticationManager
在解决了我遇到的循环依赖错误后,我开始收到此错误,现在由于某种原因,我的 AuthenticationManager bean 在我的 AuthenticationFilter 中为空
(这让我觉得我并没有真正解决它,程序现在只是提前中断了)
我的安全配置:
@Configuration
public class SecurityConfig {
@Autowired
private AuthenticationFilter authenticationFilter;
/***
* This method is used to configure the security filter chain
* @param http
* @return
* @throws Exception
*/
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
authenticationFilter.setFilterProcessesUrl("/user/login");
http
.headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable)) //h2-console fix
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement(c -> c.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(c -> c
.requestMatchers("/user/login", "/user/register", "/h2-console", "/h2-console/*").permitAll()
.anyRequest().authenticated())
.addFilterBefore(new ExceptionHandlerFilter(), AuthenticationFilter.class)
.addFilter(authenticationFilter);
return http.build();
}
}
然后是我的 AuthenticationFilter
@Component
public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try{
User user = new ObjectMapper().readValue(request.getInputStream(), User.class);
Authentication authentication = new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword());
return authenticationManager.authenticate(authentication);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
super.unsuccessfulAuthentication(request, response, failed);
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
super.successfulAuthentication(request, response, chain, authResult);
}
}
我的自定义身份验证管理器
@Component
public class CustomAuthenticationManager implements AuthenticationManager {
@Autowired
private UserService userService;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
User user = userService.getUser(authentication.getName());
if(!userService.validatePassword(authentication.getCredentials().toString(), user.getPassword())){
throw new BadCredentialsException("Invalid password");
}
return new UsernamePasswordAuthenticationToken(authentication.getName(), authentication.getCredentials());
}
}
和我的 UserServiceImpl
@Service
public class UserServiceImpl implements UserService{
@Autowired
private static BCryptPasswordEncoder bCryptPasswordEncoder;
@Autowired
private UserRepository userRepository;
@Autowired
private ModelMapper modelMapper;
@Override
public UserDto saveUser(UserDto userDto) {
userDto.setPassword(bCryptPasswordEncoder.encode(userDto.getPassword()));
return convertToDto(userRepository.save(convertToEntity(userDto)));
}
@Override
public User getUser(String email){
Optional<User> user = userRepository.findByEmail(email);
return unwrapUser(user);
}
public boolean validatePassword(String password, String encodedPassword){
return bCryptPasswordEncoder.matches(password, encodedPassword);
}
static User unwrapUser(Optional<User> user) {
if(user.isPresent()){
return user.get();
}
else throw new EntityNotFoundException("User not found");
}
private UserDto convertToDto(User user) {
return modelMapper.map(user, UserDto.class);
}
private User convertToEntity(UserDto userDto){
return modelMapper.map(userDto, User.class);
}
}
这里仍然存在我所缺少的循环依赖吗?
如果不是,是什么导致我的 AuthenticationFilter 中的authenticationManager为空?
另外,您对我将来如何调试此类错误有什么建议吗?
尝试通过构造函数而不是@Autowired注入依赖项,但结果相同 也尝试将 AuthenticationManager bean 更改为实际实现,但错误是相同的
这不是由循环引用引起的,而是因为您没有满足过滤器超类的要求。
你的课程延长了
UsernamePasswordAuthenticationFilter
延伸AbstractAuthenticationProcessingFilter
。 AbstractAuthenticationProcessingFilter 实现接口 InitializingBean
,其中包含方法 afterPropertiesSet
。在此方法中,您将看到它检查是否设置了authenticationManager。由于您没有设置它,因此断言失败。
解决此问题有两种方法:
最简单的方法是从 AuthenticationManager 中删除 Autowired 注释并将其设置在构造函数中,同时调用 super。
@Component
public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private final AuthenticationManager authenticationManager;
public AuthenticationFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
this.authenticationManager = authenticationManager;
}
}
另一种方法也同样简单:将 AuthenticationFilter 保持原样,但添加
setAuthenticationManager
的实现。
@Override
@Autowired
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
super.setAuthenticationManager(authenticationManager);
}
其中任何一个都应该可以解决您的问题。