I'm trying to make basic authentication in spring boot (2.5.3), and call UserNotFoundException when cant found user at DB.
@Override
public User findByUserName(String username){
try {
return (User) template.queryForObject("SELECT * FROM USERS WHERE email = ?",
new BeanPropertyRowMapper(User.class), username);
} catch (EmptyResultDataAccessException e) {
throw new UsernameNotFoundException("User not found");
}
}
But as a result I get message "Bad Credential". My exception has changed by BadCredential Exception.
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
public void onAuthenticationFailure(
HttpServletRequest request,
HttpServletResponse response,
AuthenticationException ex) throws IOException, ServletException {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
//HttpStatus.FORBIDDEN
Map<String, Object> data = new HashMap<>();
data.put(
"timestamp",
Calendar.getInstance().getTime());
data.put(
"exception",
ex.getMessage());
System.out.println(ex.getClass());
response.getOutputStream()
.println(objectMapper.writeValueAsString(data));
}
class org.springframework.security.authentication.BadCredentialsException
What should I override to make ability to see UserNotFoundException error message ?
CodePudding user response:
Make custom Auth provider
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Autowired
private Repository repository;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String name = authentication.getName();
String password = authentication.getCredentials().toString();
User user = repository.findByUserName(name);
if(!encoder().matches(password, user.getPassword())){
throw new BadCredentialsException("Bad credentials");
}
return new UsernamePasswordAuthenticationToken(user, password,
Arrays.asList(new SimpleGrantedAuthority("USER_ROLE")));
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
@Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
}
Like there explained https://www.baeldung.com/spring-security-authentication-provider
CodePudding user response:
You can configure the AuthenticationProvider to throw a UsernameNotFoundException instead of a BadCredentialsException when the username is not found.
Be aware that this is considered less secure.
From the setHideUserNotFoundExceptions Javadoc:
By default the
AbstractUserDetailsAuthenticationProviderthrows aBadCredentialsExceptionif a username is not found or the password is incorrect. Setting this property tofalsewill causeUsernameNotFoundExceptions to be thrown instead for the former. Note this is considered less secure than throwingBadCredentialsExceptionfor both exceptions.
If you choose to do this, below is an example of how to use setHideUserNotFoundExceptions
@Bean
public DaoAuthenticationProvider daoAuthenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(customUserDetailsService);
provider.setPasswordEncoder(customPasswordEncoder);
provider.setHideUserNotFoundExceptions(false) ;
return provider;
}
