Search code examples
javaspringspring-bootspring-security

The difference between UserDetailsService and the class that implements it


Does it make sense to create your own class that implements the UserDetailsService interface? In many examples, I see how the UserDetailsService is embedded in the security configuration class, and not the class that implements it. What's the difference? And why, when I enter the wrong username and password, I don't get the error message that I registered in PersonDetailsService? "Bad credentials" is coming out. I'm a beginner and just started learning spring security

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    private final PersonDetailsService personDetailsService;

    @Autowired
    public SecurityConfig(PersonDetailsService personDetailsService) {
        this.personDetailsService = personDetailsService;
    }

    @Autowired
    void configure(AuthenticationManagerBuilder builder) throws Exception {
        builder.userDetailsService(personDetailsService);
    }

    @Bean
    public PasswordEncoder getPasswordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }

}

@Service
public class PersonDetailsService implements UserDetailsService {
    private final PeopleRepository peopleRepository;

    @Autowired
    public PersonDetailsService(PeopleRepository peopleRepository) {
        this.peopleRepository = peopleRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Optional<Person> person = peopleRepository.findByUsername(username);

        if (person.isEmpty())
            throw new UsernameNotFoundException("User not found");

        return new PersonDetails(person.get());
    }
}


Solution

  • For your first question you spring security can authenticate multiple ways such as in memory and DB . in UserdetailsService and loadUserByUsername method you can customize how to authenticate users . and if you want DB mode you have multiple tables is DB and you can tell spring for finding username and password which table and columns must be check . for your second question put break point on your if statement and check what is person found . I think if it doesn't return username you have to use this if :

    if(person.get()==null)
       throw new UsernameNotFoundException("User not found");