Spring Boot 2.7.x升级至3.0.0后如何正确使用UserDetailsService?
Spring Boot 3.0 中 UserDetailsService 配置的正确写法
Spring Boot 3.0 对应 Spring Security 6.x,核心变化是移除了WebSecurityConfigurerAdapter,改用组件式的Bean配置。以下是适配后的完整代码:
1. UserDetailsImpl 实现(与2.7版本基本一致)
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.util.Collection; public class UserDetailsImpl implements UserDetails { private Long id; private String username; private String password; private Collection<? extends GrantedAuthority> authorities; // 构造方法、getter/setter、builder方法按需实现 @Override public Collection<? extends GrantedAuthority> getAuthorities() { return authorities; } @Override public String getPassword() { return password; } @Override public String getUsername() { return username; } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } }
2. UserDetailsServiceImpl 实现(与2.7版本基本一致)
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; @Service public class UserDetailsServiceImpl implements UserDetailsService { private final UserRepository userRepository; // 构造注入替代@Autowired public UserDetailsServiceImpl(UserRepository userRepository) { this.userRepository = userRepository; } @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userRepository.findByUsername(username) .orElseThrow(() -> new UsernameNotFoundException("用户不存在: " + username)); // 转换为UserDetailsImpl,根据实际业务构造权限集合 return UserDetailsImpl.builder() .id(user.getId()) .username(user.getUsername()) .password(user.getPassword()) .authorities(user.getAuthorities()) .build(); } }
3. WebSecurityConfig 配置(Spring Boot3 核心变化)
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableWebSecurity public class WebSecurityConfig { private final UserDetailsServiceImpl userDetailsService; public WebSecurityConfig(UserDetailsServiceImpl userDetailsService) { this.userDetailsService = userDetailsService; } // 必须显式定义密码编码器,Spring Security6不再提供默认实现 @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } // 配置认证提供者,关联UserDetailsService和密码编码器 @Bean public DaoAuthenticationProvider authenticationProvider() { DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); authProvider.setUserDetailsService(userDetailsService); authProvider.setPasswordEncoder(passwordEncoder()); return authProvider; } // 获取AuthenticationManager @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception { return authConfig.getAuthenticationManager(); } // 核心安全过滤链配置,替代原configure(HttpSecurity http)方法 @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.csrf(csrf -> csrf.disable()) // 按需启用/禁用CSRF .authorizeHttpRequests(auth -> auth .requestMatchers("/public/**", "/login").permitAll() // 公开访问路径 .anyRequest().authenticated() // 其余路径需认证 ) .formLogin(form -> form .loginPage("/login") // 自定义登录页路径,若无则用默认页 .defaultSuccessUrl("/home", true) .permitAll() ) .logout(logout -> logout.permitAll()); http.authenticationProvider(authenticationProvider()); return http.build(); } }
关键变化说明
- 移除了继承
WebSecurityConfigurerAdapter的写法,改用@Bean定义SecurityFilterChain配置HTTP安全规则 - 必须显式注册
PasswordEncoderBean,Spring Security6不再自动提供默认编码器 - 认证逻辑通过
DaoAuthenticationProvider关联UserDetailsService和密码编码器 - 推荐使用构造注入替代
@Autowired注入依赖
内容的提问来源于stack exchange,提问作者Đỗ Như Vỹ
相关产品推荐
相关产品推荐

