Spring Boot自定义SecurityFilterChain未生效问题求助
搭建Spring Boot应用配置基础登录功能时,已添加带@Configuration和@EnableWebSecurity注解的SecurityConfig类,且包含返回SecurityFilterChain的@Bean方法,但运行时系统仍使用DefaultSecurityFilterChain,要求用控制台输出的user账号和自动生成的密码登录,自定义配置未被识别。运行时除主方法的Hello World外,无自定义配置和UserDetailsService相关的日志输出,自定义用户也无法被识别。
SecurityConfig代码
@Configuration @EnableWebSecurity public class SecurityConfig { @Autowired private ArchlandsUserDetailsService userDetailsService; @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { System.out.println("In securityFilterChain"); http .csrf().disable() .authorizeHttpRequests((requests) -> requests .requestMatchers("archlands/api/**").hasRole("USER") .anyRequest().authenticated() ) .formLogin((form) -> form .loginPage("/login").permitAll() ) .logout((logout) -> logout.permitAll()) .authenticationProvider(authenticationProvider()); return http.build(); } @Bean public AuthenticationProvider authenticationProvider() { DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(); authenticationProvider.setUserDetailsService(userDetailsService); return authenticationProvider; } }
ArchlandsUserDetailsService代码
@RequiredArgsConstructor @Service @Slf4j public class ArchlandsUserDetailsService implements UserDetailsService { @Autowired private UserService userService; @Override public UserDetails loadUserByUsername(String username) { String cleanedUsername = ArchlandsInputSanitizer.clean(username); log.info("User " + cleanedUsername + " is attempting to access the Archlands."); System.out.println("User " + cleanedUsername + " is attempting to access the Archlands."); Set<GrantedAuthority> grantedAuthorities = new HashSet<>(); UserDto user = userService.findById(cleanedUsername); if (user == null) { log.error("No user exists with user id: " + cleanedUsername); throw new UsernameNotFoundException("No user exists with user id: " + cleanedUsername); } if (user.getStatus().equals("Active")) { grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_USER")); } for (int i = 0; i < user.getRoles().length; i++) { if (user.getRoles()[i].equals(Role.DM_ROLE)) { grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_DM")); } } log.info("User: " + cleanedUsername + " has authorities: " + grantedAuthorities.toString()); return new User(user.getId(), user.getPassword(), grantedAuthorities); } }
控制台输出
控制台自动生成默认用户密码,示例如下:
Using generated security password: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
1. 检查配置类包扫描范围
确保SecurityConfig所在包被Spring Boot主类的@SpringBootApplication注解覆盖扫描。如果主类在com.example.demo,而配置类在com.example.demo.config则默认会被扫描;若配置类在其他独立包,需在主类添加@ComponentScan(basePackages = "你的配置类包路径")指定扫描范围。
2. 为认证提供者添加密码编码器
Spring Security 5+强制要求配置密码编码器,否则DaoAuthenticationProvider不会生效,系统会 fallback到默认用户认证。修改authenticationProvider方法:
@Bean public AuthenticationProvider authenticationProvider() { DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(); authenticationProvider.setUserDetailsService(userDetailsService); // 这里用BCrypt编码器,需和用户密码存储的加密方式匹配 authenticationProvider.setPasswordEncoder(new BCryptPasswordEncoder()); return authenticationProvider; }
同时确保UserDto中存储的密码是对应编码器加密后的结果(比如BCrypt加密字符串)。
3. 修正请求匹配器路径格式
requestMatchers("archlands/api/**")缺少开头斜杠,应改为requestMatchers("/archlands/api/**"),否则路径匹配失效,安全规则无法生效。
4. 调整日志配置
确保ArchlandsUserDetailsService的日志能正常输出,在application.properties中添加:
logging.level.你的包路径.ArchlandsUserDetailsService=INFO
替换你的包路径为该类实际所在的包(比如com.example.demo.service)。
5. 验证UserService查询逻辑
检查userService.findById(cleanedUsername)是否能正确返回用户数据,若该方法始终返回null,会触发UsernameNotFoundException,但因配置未生效,不会走到这一步。可单独编写测试用例验证UserService的查询功能。
6. 强制禁用默认安全配置(可选)
若上述步骤无效,可在SecurityConfig的@EnableWebSecurity注解中添加excludeDefaults = true,强制禁用默认配置,确保自定义配置被加载:
@Configuration @EnableWebSecurity(excludeDefaults = true) public class SecurityConfig { // ... 原有代码 }
内容的提问来源于stack exchange,提问作者Fidelis

