JavaServlet过滤器:我必须在传递到链之前添加头,文档告诉我不是这样

JavaServlet过滤器:我必须在传递到链之前添加头,文档告诉我不是这样,java,servlets,filter,Java,Servlets,Filter,我们目前正在为应用程序的每个响应添加标题。为了添加这些标题,我们使用ServletAPIFilter-接口 我们的应用程序中有以下过滤器: public class SecurityFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void do

我们目前正在为应用程序的每个响应添加标题。为了添加这些标题,我们使用ServletAPI
Filter
-接口

我们的应用程序中有以下过滤器:

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()
    {

    }
}
这(特别是
doFilter
-方法)是根据文档正确实现的,文档建议了以下工作顺序:

  • 检查请求
  • (可选)使用自定义实现包装请求对象,以过滤输入过滤的内容或标题
  • (可选)使用自定义实现包装响应对象,以过滤内容或标题以进行输出过滤

    • 使用FilterChain对象(chain.doFilter())调用链中的下一个实体
    • 或者不将请求/响应对传递给过滤器链中的下一个实体以阻止请求处理
  • 在调用过滤器链中的下一个实体后,直接在响应上设置头
  • 据我们所见,根据文档,我们的
    doFilter
    -方法的顺序是正确的(如第4点所述首先将请求传递给链,然后如第5点所述添加自定义头)。但是,我们添加的标题在响应中不可见。如果我们改为以下顺序,一切似乎都正常:

    @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);
    }
    

    有人能解释这种行为吗?

    我不知道您指的是Servlet规范的哪个版本,但在3.1第6.2.1章“过滤器生命周期”中,我读到了(我的重点):

  • 调用链中的下一个过滤器后,过滤器可能会检查响应头
  • “检查”不是“设置”!实际上,header方法的规范说(Servlet 3.1,第5.2章“Headers”):

    要成功地传输回客户端,必须在提交响应之前设置头。提交响应后设置的头将被servlet容器忽略

    我猜这是发生在您的请求上的,一些servlet或过滤器正在“提交”,因此忽略了头


    底线:规范(至少我在3.1中看到的)不建议在调用
    chain.doFilter()后设置标题。你的第二个版本是正确的(我一直都在实现添加标题的过滤器)

    Oracle告诉您,如果要在
    chain.doFilter(…)

    请注意,如果要预处理请求对象或后处理 对于响应对象,不能直接操纵原始对象 请求或响应对象。你必须用包装纸。后处理时 例如,一个响应,目标servlet已经完成并且 在筛选器启动时,响应可能已经提交 有机会对回复做任何事情你必须通过考试 响应包装器,而不是链中的原始响应 doFilter()调用。请参阅“使用筛选器包装和更改请求或 答复”


    还有其他过滤器吗?@EvanKnowles有。我认为这是问题的一部分,正如Nikos Paraskevopoulos在下面指出的,另一个过滤器很可能会提交请求。感谢您的回复。在我们阅读了规范3.0的文档后,我刚刚提交了更改。文档与您引用的相同。愚蠢的代码注释如何为
    doFilter
    -方法使用令人困惑的描述。。。