Java Servlet Filter: I have to add headers before passing to the chain, the documentation says otherwise

We are currently working on adding headers for each response from our application. To add these headers, we use the Servlet Filter -interface APIs.

We have the following filter in our application:

 public class SecurityFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(request, response); HttpServletResponse httpServletResponse = ((HttpServletResponse) response); httpServletResponse.addHeader("X-Frame-Options", "DENY"); httpServletResponse.addHeader("X-Content-Type-Options", "nosniff"); } @Override public void destroy() { } } 

This (in particular, the doFilter method) is executed correctly in accordance with the documentation, which assumes the following procedure:

  • Examine the request
  • It is not necessary to wrap the request object with a special implementation for filtering content or headers for filtering input.
  • Optionally wrap the response object with a special implementation for filtering content or headers for filtering output.

    • Or call the next object in the chain using the FilterChain object (chain.doFilter ()),
    • or do not pass a request / response pair to the next object in the filter chain to block request processing
  • Set the response headers directly after calling the next object in the filter chain.

As far as we can see, the order of our doFilter method is correct in accordance with the documentation (first pass the request to the chain as indicated in paragraph 4, then add custom headers as indicated in paragraph 5). However, the headers we add do not appear in the responses. If we change the order to the following, everything will work fine:

 @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse httpServletResponse = ((HttpServletResponse) response); httpServletResponse.addHeader("X-Frame-Options", "DENY"); httpServletResponse.addHeader("X-Content-Type-Options", "nosniff"); chain.doFilter(request, response); } 

Can anyone explain this behavior?

+5
source share
2 answers

I don’t know which version of the servlet specification you have in mind, but in 3.1, chapter 6.2.1, β€œFilter Life Cycle,” I read (emphasis mine):

  1. After calling the next filter in the chain, the filter can examine the response headers.

Explore, not install! In fact, the specification for header methods says (Servlet 3.1, chapter 5.2 "Headers"):

To be successfully passed to the client, headers must be set before the response is executed. The headers set after the response will be ignored by the servlet container.

I assume that this happens with your request, some kind of servlet or filter down the chain "commits", so the headers are ignored.

Bottom line: The specification (at least as far as I see in 3.1) is not suitable for setting headers after calling chain.doFilter() . Your second version, which works, is correct (and as I always applied filters that add headers)!

+2
source

Oracle suggests you wrap the answer before passing it in a chain if you want to add something after chain.doFilter(..)

Note that if you want to pre-process the request object or the postprocess response object, you cannot directly manipulate the original request or response object. You must use wrappers. When the post-processing of the response, for example, the target servlet is already completed and the response can already be fixed by the time the filter has a chance to do something with the response. You should go through the response wrapper instead of the original response in the doFilter () chain. See "Using a Filter to Wrap and Modify a Request or Response."

http://docs.oracle.com/cd/B32110_01/web.1013/b28959/filters.htm#BCFCIHAH

+3
source

All Articles