检查了有相同错误的类似线程,但仍然无法找到错误的原因。我正在遵循教程并尝试使用spring创建简单的用户名和密码登录页面,以及实现用户的两个角色。
这是我的securityConfig文件和我的userserviceimplementation文件导致这个错误。
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, jsr250Enabled = true)
public class SecurityConfig 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());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
auth.setUserDetailsService(userService);
auth.setPasswordEncoder(passwordEncoder());
return auth;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/ws").permitAll()
.antMatchers("/users").hasAnyAuthority(Role.ADMIN.name())
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/login-error")
.loginProcessingUrl("/auth")
.permitAll()
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/").deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
.and()
.csrf().disable();
}
}`
@Service
public class UserServiceImplement implements UserService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
public UserServiceImplement(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()
.name(userDto.getUsername())
.password(passwordEncoder.encode(userDto.getPassword()))
.email(userDto.getEmail())
.role(Role.USER)
.build();
userRepository.save(user);
return true;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findFirstByName(username);
if (user == null) {
throw new UsernameNotFoundException("User was not found with this name" + username);
}
List<GrantedAuthority> roles = new ArrayList<>();
roles.add(new SimpleGrantedAuthority(user.getRole().name()));
return new org.springframework.security.core.userdetails.User(
user.getName(),
user.getPassword(),
roles
);
}
}
类SecurityConfig
提供一个PasswordEncoder
,需要一个UserService
。UserServiceImplement
类是UserService
,需要PasswordEncoder
。换句话说,要创建SecurityConfig
,您需要UserService
,但要创建UserService
,您需要SecurityConfig
来提供PasswordEncoder
。
最简单的修复方法可能是将PasswordEncoder
方法移到SecurityConfig
之外。另一种方法是将UserServiceImplement
视为POJO(删除@Service
注释),并在authenticationProvider
方法中手动创建它。你需要一个UserRepository
,但是你可以使用方法参数注入:
@Bean
public DaoAuthenticationProvider authenticationProvider(UserRepository userRepository) {
PasswordEncoder passwordEncoder = passwordEncoder();
UserService userService = new UserServiceImplement(userRepository, passwordEncoder);
DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
auth.setUserDetailsService(userService);
auth.setPasswordEncoder(passwordEncoder);
return auth;
}