I have:
@Service
public class MyAppUserDetailsService implements UserDetailsService {
@Autowired
private IUserInfoDAO userInfoDAO;
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
User activeUserInfo = userInfoDAO.getActiveUser(userName);
GrantedAuthority authority = new SimpleGrantedAuthority(activeUserInfo.getRole());
String userNameVal = activeUserInfo.getUserName();
String userSurnameVal = activeUserInfo.getPassword();
UserDetails userDetails = new org.springframework.security.core.userdetails.User(userNameVal, userSurnameVal, Arrays.asList(authority));
return userDetails;
}
}
and:
in security chain I configured:
.and().formLogin() //login configuration
.loginPage("/app/login")
.loginProcessingUrl("/app-login")
.usernameParameter("app_username")
.passwordParameter("app_password")
.defaultSuccessUrl("/app/secure/projects-details")
How user password fill in the form is compare to UserDetails set in loadUserByUsername method?
Once you tell the Spring Security Configuration that you will use a particular
UserDetailsServiceor only one@Servicebean is an implementation of that interface, then Spring starts using it to fetch the user by username from your persistent storage. Let's simplify the flow:The user submits a form where fields with names
app_usernameandapp_passwordare present (as configured in Web Security Config) to theloginPage(String)routeThe form submission is intercepted by the Spring Security's Filter Chain and Spring is aware that the username is in the field
app_usernameand the password is in the fieldapp_passwordThe configured
UserDetailsServicebean is now activated, at itsloadUserByUsername(String)method is invoked and the value ofapp_usernamefield is passed (e.g.john_smith)As the
loadUserByUsername(String)method is by contract designed to return an implementation ofUserDetailsit always returns an object which containsgetUsername()andgetPassword()methodsSpring then uses the
getPassword()method from the contract and compares the password withapp_passwordfield (e.g.super_s3cr3t_password)If
passwordEncoder()is configured in the Spring Security Config or an implementation ofPasswordEncoderinterface is registered as bean, then spring uses theisPasswordValid(String, String, Object)method to verify the contents ofapp_passwordfield and the result ofUserDetails.getPassword()methodIf the
UserDetailsServicedoes not throwUsernameNotFoundExceptionand the fetchedUserDetails'sgetPassword()matches theapp_passwordthe filter chain continues executing the other filters, otherwise it prevents the user from logging into the applicationIf a code example simplifies it better, then imagine the following pseudo-java-code:
Keep in mind this is not the Spring Security Code behind the scenes, but just a simplified code illustration of the explanation.