Spring Boot: как запустить проверку бинов перед аутентификацией? - PullRequest
0 голосов
/ 04 мая 2018

Я новичок в Spring Boot.

Я хотел бы знать, как я могу проверить DTO Credentials перед аутентификацией в 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.

Ответы [ 2 ]

0 голосов
/ 04 мая 2018

Я предполагаю, что проблема в том, что Spring обрабатывает аутентификацию еще до того, как ваш метод Post будет достигнут. Поэтому проверка бина никогда не будет выполняться на 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;
    }

}
0 голосов
/ 04 мая 2018

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