Какое исключение лучше всего подходит для описания отсутствия Spring Security Principal в дизайне RESTful, например, когда я получаю null при получении принципала от SecurityContextHolder.getContext().getAuthentication().getPrincipal()?

У меня есть проект с настраиваемой службой авторизации, и одной его части нужна информация о принципале, который вошел в систему, и какие у него есть полномочия.

Некоторые (но не все) конечные точки REST также защищены Spring Security.

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

С одной стороны, наиболее подходящим исключением является AccessDeniedException (Http 403), но, с другой стороны, может быть более безопасным подходом выдать 500 или 404, чтобы «скрыть» существование запрошенного ресурса. .

Я думал о следующих исключениях:

  • HttpStatus: 500, вызванный org.springframework.security.access.AuthorizationServiceException
  • HttpStatus: 403 org.springframework.security.access.AccessDeniedException
  • HttpStatus: 500 caused by java.lang.IllegalStateException
  • HttpStatus: 500 caused by java.lang.NullPointerException

Я не уверен, какой подход лучше - запретить, скрыть или выдать внутреннюю ошибку сервера.

0
Dariusz Janicki 22 Окт 2019 в 08:31

1 ответ

Если вы используете Spring Security и настраиваемую службу авторизации, у вас, вероятно, есть что-то вроде этого:

@Component
public class CustomAccessDeniedHandler extends AccessDeniedHandlerImpl {
    private final String HOME_PAGE = "/index.html";

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();

        if (auth != null) {

            if (auth instanceof AnonymousAuthenticationToken) {
                response.sendRedirect("/#/login");
                super.handle(request, response, e);
                return;
            }

            if (auth.getAuthorities().iterator().next().getAuthority().equals("ROLE_EMPLOYEE") || auth.getAuthorities().iterator().next().getAuthority().equals("ROLE_ADMIN") ) {
                 response.sendRedirect("/dashboard/Dashboard.xhtml");
                 super.handle(request, response, e);
                 return;
            }     
             response.sendRedirect("/#/dashboard/user");        
        }
        super.handle(request, response, e);
    }
}  

В вашем случае в приложении я бы предпочел перенаправить на экран входа в систему, как показано выше, с сообщением вида Please log in.

В API я бы вернул ответ 404 - Resource not found.

1
Oliver 22 Окт 2019 в 09:22
1
Извините, но я не упомянул, что некоторые конечные точки REST не защищены, например. у них есть разрешение Spring SecurityAll() на них. Меня очень беспокоит то, что может случиться так, что разработчик вернет конфиденциальные данные, работая с другой незащищенной конечной точкой REST. Вот почему я ввел еще один уровень безопасности. Так что ваш первый ответ с перенаправлением на страницу входа не будет применяться к моему решению.
 – 
Dariusz Janicki
22 Окт 2019 в 11:49
И вторая часть вашего ответа: можете ли вы уточнить, почему вы выбрали ответ 404? Вы ссылаетесь на какой-то отраслевой стандарт?
 – 
Dariusz Janicki
22 Окт 2019 в 11:50