2 цепочки AbstractAuthenticationProcessingFilter, приводящие к перенаправлению 302, когда 2-й фильтр пытается выполнить запись в поток ответа - PullRequest
0 голосов
/ 01 февраля 2019

У меня есть 2 фильтра, Filter1 и Filter2, оба из которых расширяют AbstractAuthenticationProcessingFilter.Filter1 успешно выполнил свою работу и приковал запрос к Filter2.Теперь, когда Filter2 выдает AuthenticationException и обрабатывается методом onAuthenticationFailure Filter2, ответ записывается в поток ответов с помощью HttpStatus 403 и, следовательно, ответ фиксируется.Но элемент управления возвращается к Filter1 после вызова метода doFilter (в Filter1), и он перенаправляет на '/' url, что приводит к перенаправлению статуса 302 вместо 403, что я ожидаю.Кто-нибудь есть идеи о том, как пропустить фильтр цепочки во время исключения, чтобы избежать перенаправления на «/» URL?

Это приложение с начальной загрузкой, и оба фильтра настроены в ApplicationConfig.java с отдельными ErrorHandlers Errorhandler1 и Errorhandler2.FirstFilter установил для статуса аутентификации значение true, а второй фильтр создает исключение.Но поскольку Response уже зафиксирован Errorhandler2 ('AuthenticationFailureHandler') второго фильтра в цепочке, но управление все равно переходит к Filter1 и перенаправляет на '/'.

@Component
public class Filter2CustomErrorhandler implements AuthenticationFailureHandler {

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        CustomError error = new CustomError();
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(403);
        response.getWriter().write(convertObjectToJson(error));
    }

    private String convertObjectToJson(Object object) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        return mapper.writeValueAsString(object);
    }

}

public class Filter1 extends AbstractAuthenticationProcessingFilter {

    public Filter1(RequestMatcher requiresAuthenticationRequestMatcher) {
        super(requiresAuthenticationRequestMatcher);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        Authentication authentication = new CustomAuthenticationToken("some-principal-1", "some-credential-1");
        authentication.setAuthenticated(true);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        return authentication;
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
                                            Authentication authResult) throws IOException, ServletException {
        super.successfulAuthentication(request, response, chain, authResult);
            chain.doFilter(request, response);
    }

    @Override
    public void setAuthenticationFailureHandler(AuthenticationFailureHandler failureHandler) {
        super.setAuthenticationFailureHandler(failureHandler);
    }
}   


public class Filter2 extends AbstractAuthenticationProcessingFilter {

    public Filter2(RequestMatcher requiresAuthenticationRequestMatcher) {
        super(requiresAuthenticationRequestMatcher);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        Authentication authentication = new CustomAuthenticationToken("some-principal-2", "some-credential-2");
        authentication.setAuthenticated(true);

        throw new SecurityAuthenticationException("some-exception-message", new CustomException());

        //SecurityContextHolder.getContext().setAuthentication(authentication);
        //return authentication;
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
                                            Authentication authResult) throws IOException, ServletException {
        super.successfulAuthentication(request, response, chain, authResult);
            chain.doFilter(request, response);
    }

    @Override
    public void setAuthenticationFailureHandler(AuthenticationFailureHandler failureHandler) {
        super.setAuthenticationFailureHandler(failureHandler);
    }
} 

Я ожидаюHttpStatus 403 в RestClient.

1 Ответ

0 голосов
/ 11 февраля 2019

Решение:

  • Таким образом, еще один способ достичь этого - иметь одного AbstractAuthenticationProcessingFilter и нескольких поставщиков.

  • Отдельные поставщики могут реализоватьПереопределено поддерживает метод для определенного типа Authentication (например, ExampleAuthInstance extends Authentication).

  • Когда вы вызываете провайдеров из фильтра, например this.getAuthenticationManager().authenticate( exampleAuthInstance ), провайдер, который поддерживает ExampleAuthInstance, метод аутентификацииэтого провайдера. Будет вызываться

  • AuthenticationException из самого фильтра, а не из провайдеров.Поставщики скорее могут выдать CustomSecurityException с требуемым HttpStatus, который затем можно обернуть в AuthenticationException и выбросить на уровне фильтра.Который затем будет делегирован соответствующему предварительно сконфигурированному Failure handler, который может захотеть поток ответа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...