Spring Boot: как запустить Bean Validation перед аутентификацией?

Я новичок в 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.

Я немного смущен целью вашего метода публикации. Мне кажется, что вы часто выполняете аутентификацию вручную. Никогда не следует выполнять аутентификацию вручную для вашего сопоставления. Аутентификация является критическим аспектом и должна выполняться в выделенных классах. Spring уже имеет множество встроенных функций, которые вы можете адаптировать и изменять в соответствии со своими потребностями. Вам следует изучить GlobalMethodSecurityConfiguration и UserDetailsService.

kkflf 04.05.2018 20:45
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
1
349
2

Ответы 2

Вы можете добавить реализацию 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);
    }
}

Покажите мне, пожалуйста, пример!

Luciano Borges 04.05.2018 20:31

@LucianoBorges, просто из любопытства, тебе удалось решить свою проблему?

Maarten 17.05.2018 10:35

Я предполагаю, что проблема в том, что 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;
    }

}

Другие вопросы по теме