简体   繁体   中英

Spring Security and BCryptPasswordEncoder for registration and login

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM