I am new in Java Spring and I want to create a system with registration for users, which are stored in my DB (Postgres), where a password is stored encrypted by BCryptPasswordEncoder. The registration process is working fine, but when I want to log in, I always get an "Invalid username or password." message. I already search everywhere and read a lot of articles, but everything that I did had the same result.
Here is my SecurityConfiguration class:
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("customUserDetailsService")
private CustomUserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService()).and().authenticationProvider(authProvider());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/signin", "/confirm", "/error","/signup", "/css/**","/js/**","/images/**").permitAll()
.antMatchers("/admin/**").hasAuthority("ROLE_ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/signin")
.usernameParameter("username").passwordParameter("password")
.defaultSuccessUrl("/cockpit.html")
.permitAll()
.and()
.exceptionHandling().accessDeniedPage("/403")
.and()
.csrf()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/signin").and().exceptionHandling()
.accessDeniedPage("/error");
}
@Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
@Bean
public DaoAuthenticationProvider authProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(encoder());
return authProvider;
}
}
And here is my CustomUserDetailsService class:
@Service("customUserDetailsService")
public class CustomUserDetailsService implements UserDetailsService{
private final UserRepository userRepository;
private final RoleRepository userRolesRepository;
@Autowired
private PasswordEncoder bCryptPasswordEncoder;
@Autowired
public CustomUserDetailsService(UserRepository userRepository,RoleRepository userRolesRepository) {
this.userRepository = userRepository;
this.userRolesRepository=userRolesRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws
UsernameNotFoundException {
Logger LOGGER = Logger.getLogger(CustomUserDetailsService.class.getName());
User user = userRepository.findByUsername(username);
if (null == user) {
return null;
} else {
List<GrantedAuthority> authorities =
buildUserAuthority(userRolesRepository.findRoleByUserName(username));
LOGGER.info("Loaded account: " + user.getUsername() + " password: " + user.getPassword() + " password matches: " + bCryptPasswordEncoder.matches("password", user.getPassword()));
org.springframework.security.core.userdetails.User userDetails = new org.springframework.security.core.userdetails.User(user.getUsername(), Deuser.getPassword(),authorities);
return userDetails;
}
}
private List<GrantedAuthority> buildUserAuthority(Set<Role> userRoles) {
Set<GrantedAuthority> setAuths = new HashSet<>();
// add user's authorities
for (Role userRole : userRoles) {
setAuths.add(new SimpleGrantedAuthority(userRole.getRole()));
}
return new ArrayList<>(setAuths);
}
public User findByConfirmationToken(String confirmationToken) {
return userRepository.findByConfirmationToken(confirmationToken);
}
public void saveUser(User user){
user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
userRepository.save(user);
}
public void saveRole(User user) {
Role role = new Role();
role.setRole("ROLE_USER");
role.setId(user.getId());
role.setUsername(user.getUsername());
userRolesRepository.save(role);
}
}
I call the method saveUser(user) and saveRole(user) during registration. The LOGGER.info message gives me "false" for bCryptPasswordEncoder.matches("password", user.getPassword()) even I wrote right password.
SOLVED Okay, I just found out where was the mistake. I called method saveUser twice, during registration, and then during activation, so the password was encrypted twice. I solved that by adding method updateUser without using encryption.
Thank you for your help.
Try like this:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// Create a default account
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
CustomUserDetails:
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User account = userDao.getUserByUsername(username);
System.out.println("User got from DB----------------------" + account.getPassword());
boolean enabled = true;
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
User user = new User(account.getUserName(), account.getPassword(), enabled, accountNonExpired,
credentialsNonExpired, accountNonLocked, getAuthorities(account.getRole()));
System.out.println(user.getPassword());
return user;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.