Spring Boot Security OAuth - обработчик исключения InternalAuthenticationServiceException

Приложение My Spring Boot OAuth REST возвращает статус «401 Unauthorized» при сбое подключения к базе данных (Spring Security выдает InternalAuthenticationServiceException). Это странно, и мне нужно изменить статус на «500 Внутренняя ошибка сервера», чтобы клиент мог дать какое-то адекватное описание, например, «служба недоступна».

Если я использую WebResponseExceptionTranslator, я могу поймать ответ, но если я изменю статус HTTP, он будет работать только тогда, когда база данных активна. Если база данных отключена, я снова получаю «401 Unauthorized».

Как мне решить эту проблему наиболее изящно?


person TechnoPriest    schedule 26.10.2017    source источник


Ответы (2)


В зависимости от того, на каком уровне генерируется исключение, вы можете добавить обработчик исключений в свой контроллер входа:

@ExceptionHandler(InternalAuthenticationServiceException.class)
public ModelAndView handleError(HttpServletRequest req, Exception ex) {
   // convert exception to 500, add logging and
}

Узнайте больше об обработке исключений здесь: https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc.

person agilob    schedule 26.10.2017
comment
Спасибо за ваш ответ. Я не уверен, что @ExceptionHandler - это способ. К сожалению, у меня нет LoginController, и все запросы на авторизацию обрабатываются библиотекой spring-oauth. - person TechnoPriest; 26.10.2017

Я исправляю это, добавляя «try catch» вокруг запроса jdbcTemplate в моем пользовательском UserDetailService.

protected List<UserDetails> loadUsersByUsername(String username) {

       try {    

            userDetailsList = this.getJdbcTemplate().query( USERS_BY_USERNAME, new String[]{username}, 
                    new RowMapper() {
                        public UserDetails mapRow( ResultSet rs, int rowNum ) throws SQLException {
                        String username = rs.getString( 1 );

                        /* etc. map user fields */

                        return new SecurityUser( username, /* other params... */ );
                    }
            });

        } catch (CannotGetJdbcConnectionException e){

            logger.error( "UserDetailService SQL error: " + e.getMessage(), e );
        } 

        return userDetailsList; 
}

Затем я проверяю InternalAuthenticationServiceException с помощью WebResponseExceptionTranslator и меняю статус ответа.

Кажется, когда я ловлю CannotGetJdbcConnectionException, что-то в цепочке рушится. Это работает, но я оставлю свой вопрос открытым, может кто-нибудь предложит более четкое решение.

person TechnoPriest    schedule 26.10.2017