Я новичок в Spring Boot.
Я хотел бы знать, как я могу проверить учетные данные DTO перед аутентификацией в Spring Boot?
У меня такой контроллер:
@PostMapping
public ResponseEntity<TokenDTO> generateTokenJwt(@Valid @RequestBody CredentialsDTO credentials, BindingResult result)
throws AuthenticationException {
TokenDTO response = new TokenDTO();
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
credentials.username, credentials.password);
Authentication authentication = authenticationManager.authenticate(authenticationToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
UserDetails userDetails = userDetailsService.loadUserByUsername(credentials.username);
String token = jwtTokenUtils.getToken(userDetails);
response.token = token;
return ResponseEntity.ok(response);
}
DTO учетных данных:
public class CredentialsDTO {
@NotEmpty
public String username;
@NotEmpty
public String password;
}
Итак, когда я выполняю POST следующим образом:
curl -i -X POST \
-H "Accept:application/json" \
-H "Content-Type:application/json" \
-d \
'{
"username": "",
"password": "123456"
}' \
'http://localhost:8080/api/login'
Я хотел бы показать ошибку 422, сообщающую, что свойство имени пользователя не должно быть пустым, но происходит то, что сначала выполняется аутентификация, и возвращается ошибка 401.




Вы можете добавить реализацию HandlerInterceptor.
Ваша реализация метода preHandle (...) должна обрабатывать сценарий ошибки, а затем возвращать false (чтобы остановить передачу запроса другим слушателям и обработчикам).
Вы можете расширить HandlerInterceptorAdapter, чтобы упростить жизнь. Это будет выглядеть примерно так.
@Component
public class LoginInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (isRequestToLoginUrl(request)) {
return hasValidBody(request);
}
return true;
}
}
Затем вам нужно зарегистрировать этот обработчик в Spring MVC, добавив это:
@Configuration
public static class WebMvcConfig extends WebMvcConfigurerAdapter {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor);
}
}
Покажите мне, пожалуйста, пример!
@LucianoBorges, просто из любопытства, тебе удалось решить свою проблему?
Я предполагаю, что проблема в том, что Spring обрабатывает аутентификацию до того, как ваш метод Post когда-либо будет достигнут. Следовательно, проверка bean-компонентов никогда не будет выполняться на CredentialsDTO.
Я предлагаю вам создать свой собственный UserDetailsService. Это позволит вам выполнить некоторую проверку аутентификации.
Пример:
@Service
@Transactional(propagation = Propagation.REQUIRED)
public class UserSecurityService implements UserDetailsService {
@Autowired
UserRepository userRepository;
public User loadUserByUsername(String email) throws UsernameNotFoundException {
if (email.isEmpty()) {
//Throw whatever exception you see fitting
throw new UsernameNotFoundException("security.userNotFound");
}
User user = userRepository.getUserByEmail(email);
return user;
}
}
Я немного смущен целью вашего метода публикации. Мне кажется, что вы часто выполняете аутентификацию вручную. Никогда не следует выполнять аутентификацию вручную для вашего сопоставления. Аутентификация является критическим аспектом и должна выполняться в выделенных классах. Spring уже имеет множество встроенных функций, которые вы можете адаптировать и изменять в соответствии со своими потребностями. Вам следует изучить GlobalMethodSecurityConfiguration и UserDetailsService.