I have and endpoint to find devices in a database and returns a response using PageWrapper. The content type should be application/json. So far so good. Next I add Spring Security with vanilla configuration and the endpoint starts failing. It says Access denied (even with permitAll()), and the reason is it failed when creating the response. Why? Because the moment Spring calls "createOutputMessage(NativeWebRequest webRequest)" from AbstractMessageConverterMethodProcessor.class, the response is created with default Content-type ISO-8859-1. Then, a few steps later, when finding a suitable Converter to handle the response type, it finds MappingJackson2HttpMessageConverter, and application/json is OK, but it expects content-type UTF-8. Since content-type in header is ISO-8859-1 it throws an exception saying no converter found.

When removing Spring Security, the response is created with Content-type null. Thats fine and later on if content-type is null it fills it with UTF-8. Why is Security adding ISO-8859-1 as a default? And how can I force it to use UTF-8? Thanks in advance

1

There are 1 best solutions below

0
Hernan Petringa On

Found the problem:

@Override
    public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
      throws IOException, ServletException {
        try {
            Authentication authentication = getAuthentication.execute((HttpServletRequest) request);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        } catch (Exception exp) {
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            httpResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
            PrintWriter writer = httpResponse.getWriter();
            writer.print(exp.getMessage());
            writer.flush();
            writer.close();
        }

        filterChain.doFilter(request, response);
    }

In my custom filter I was catching an exception in case user didn't get authenticated, but if I was hitting a URL affected by "permitAll()", this piece of code was still executed. As permitAll() doesn't require the request to be authenticated but still hits the "doFilterInternal" code, an exception was thrown. Within the catch, there is a line saying httpResponse.getWriter(). That code intends to return an instance of Writer in order to write in the body of the response. Furthermore, it checks for the content type and charset, and since chartset is null, it uses a default charset of ISO-8859-1. Once that code is executed, that same "response" is forwarded to the Controller, and is the same response that will be used inside the Jackson converter. Then the converter is expecting that the charset is a valid one (UTF-8) in order to match it with a json response type or be null, to autocomplete it with UTF-8, but it was already set to ISO-8859-1, thus making the converter to throw a No Converter found exception. Just deleting the catch and not calling prematurely the "getWriter()" fixed the problem.