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
AbstractUserDetailsAuthenticationProvider
throws aBadCredentialsException
if a username is not found or the password is incorrect. Setting this property tofalse
will causeUsernameNotFoundException
s to be thrown instead for the former. Note this is considered less secure than throwingBadCredentialsException
for 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;
}