Learn Spring Security
Contents
Database Backed UserDetailsService
Remember we are using InMemoryUserDetailsManager, the default non-persistant implementation of UserDetailsService provided by Spring Security. It is mainly intended for testing and demonstration purposes. Any change in the user details in the database requires us to restart the application. We need an implementation backed by database for production.
UserDetailsService
UserDetailsService is used by DaoAuthenticationProvider for retrieving a username, password, and other attributes for authenticating with a username and password. We can define custom authentication by exposing a custom UserDetailsService as a bean.
Let's implement it using our DbUserDetailsService bean by overriding the loadUserByUsername() method.
@Service
public class DbUserDetailsService implements UserDetailsService {
// Other details omitted for brevity
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
AppUser appUser = appUserRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException(String.format("User %s not found", username)));
return User.builder()
.username(appUser.getUsername())
.password(appUser.getPassword())
.authorities(this.getPermissions(appUser.getRoles()))
.build();
}
}
Here we are using AppUserRepository to find the user by username from the database. And then we are returning the UserDetails object mapped from the AppUser object.
Once we remove the InMemoryUserDetailsManager bean from SecurityBean configuration, DaoAuthenticationProvider will automatically use the DbUserDetailsService component to load the user by username for authentication. And we can also remove the existing loadAllUserDetails() method as it is no longer required.
Note
Please note there is no change in the security restrictions we have applied so far as we have just swapped the UserDetailsService implementation from non-persistant datastore to persistant datastore.