已配置PasswordEncoder Bean仍报错:Spring Security无法找到该Bean
问题:Spring Security中已定义PasswordEncoder Bean但启动报错
我正在用Spring Security和JWT实现API认证,注册功能里用PasswordEncoder加密密码。已经在AppConfig配置类中定义了PasswordEncoder类型的Bean,但启动应用时出现以下错误:
*************************** APPLICATION FAILED TO START *************************** Description: Parameter 1 of constructor in com.akuntansi.akuntansi.repo.AuthenticationService required a bean of type 'org.springframework.security.crypto.password.PasswordEncoder' that could not be found. Action: Consider defining a bean of type 'org.springframework.security.crypto.password.PasswordEncoder' in your configuration.
配置类代码(AppConfig)
package com.akuntansi.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import com.akuntansi.akuntansi.repo.UserRepo; import lombok.RequiredArgsConstructor; @Configuration @RequiredArgsConstructor public class AppConfig { private final UserRepo userRepo; @Bean public UserDetailsService userDetailsService(){ return username -> userRepo.findByUsername(username).orElseThrow(() -> new UsernameNotFoundException("User not found!")); } @Bean public AuthenticationProvider authenticationProvider(){ DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); authProvider.setUserDetailsService(userDetailsService()); authProvider.setPasswordEncoder(passwordEncoder()); return authProvider; } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception{ return config.getAuthenticationManager(); } }
AuthenticationService类代码
package com.akuntansi.akuntansi.repo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import com.akuntansi.akuntansi.model.Role; import com.akuntansi.akuntansi.model.Users; import lombok.RequiredArgsConstructor; @Service @RequiredArgsConstructor public class AuthenticationService { private final UserRepo userRepo; private final PasswordEncoder passwordEncoder; private final JWTService jwtService; private final AuthenticationManager authenticationManager; public AuthenticationResponse register(RegisterRequest request){ var user = Users.builder() .username(request.getUsername()) .password(passwordEncoder.encode(request.getPassword())) .role(Role.USER) .build(); userRepo.save(user); var jwtToken = jwtService.generateJwtToken(user); return AuthenticationResponse.builder() .token(jwtToken) .build(); } public AuthenticationResponse login(AuthenticationRequest request){ authenticationManager.authenticate( new UsernamePasswordAuthenticationToken( request.getUsername(), request.getPassword() ) ); var user = userRepo.findByUsername(request.getUsername()).orElseThrow(); var jwtToken = jwtService.generateJwtToken(user); return AuthenticationResponse.builder() .token(jwtToken) .build(); } }
问题原因及解决方案
核心原因
Spring容器没有扫描到你的AppConfig配置类,导致其中定义的PasswordEncoder Bean未被注册,而AuthenticationService依赖该Bean,因此启动时报错。
从包结构来看:
AppConfig在com.akuntansi.config包AuthenticationService在com.akuntansi.akuntansi.repo包
Spring默认组件扫描范围是主启动类所在包及其子包,如果主启动类在com.akuntansi.akuntansi下,com.akuntansi.config不在默认扫描范围内,AppConfig不会被加载。
解决方案
方案1:扩展组件扫描范围
在Spring Boot主启动类上添加@ComponentScan注解,指定根扫描包,确保包含com.akuntansi.config:
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; @SpringBootApplication @ComponentScan(basePackages = {"com.akuntansi"}) public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } }
方案2:调整配置类位置
将AppConfig移动到主启动类所在包或其子包下,比如主启动类在com.akuntansi.akuntansi,就把AppConfig移到com.akuntansi.akuntansi.config包中,让Spring默认扫描覆盖到。
额外检查
确保项目已引入Spring Security依赖,比如Maven的spring-boot-starter-security,依赖缺失也会导致相关Bean无法正常注册。
内容的提问来源于stack exchange,提问作者Timothy Justin William
相关产品推荐
相关产品推荐

