2015-05-20 21 views
5

我們目前正在爲來自應用程序的每個響應添加頭文件。爲了添加這些頭文件,我們使用Servlet API Filter -interface。根據該文件,這表明了以下工作順序Java Servlet過濾器:我必須在傳遞到鏈之前添加頭文件,文檔告訴其他方式

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 - 方法)實施正確:

我們有以下過濾器在我們的應用

  1. 檢查請求
  2. (可選)使用自定義實現包裝請求對象以過濾輸入的內容或標頭f iltering
  3. 任選地包住響應對象與自定義實現來過濾內容或標題爲輸出濾波

    • 要麼使用FilterChain對象調用下一個實體在鏈(chain.doFilter()),
    • 或不能在請求/響應對傳遞到下一個實體在過濾器鏈,以阻止請求處理在過濾器鏈中的下一個實體的調用之後的響應
  4. 直接設置標頭。

據我們可以看到,我們的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); 
} 

任何人都可以解釋這種行爲?

+0

是否有任何其他過濾器? –

+0

@EvanKnowles有。我認爲這是問題的一部分,因爲Nikos Paraskevopoulos指出下面的另一個過濾器很可能會提出請求。 –

回答

2

我不知道你指的是什麼Servlet規範的版本,但在3.1,章6.2.1「過濾器生命週期」我讀(重點煤礦):

  • 在調用鏈中的下一個過濾器之後,過濾器可能會檢查響應標頭。
  • 「檢查」不是「設置」!實際上,標題方法的規格說明(Servlet 3.1,第5.2章「標題」):

    要成功傳回客戶端,必須在提交響應之前設置標頭。提交響應之後設置的頭部將被servlet容器忽略。

    我想這是發生在您的請求,一些servlet或過濾器的鏈是「提交」,所以頭被忽略。

    底線:在調用chain.doFilter()之後,規範(至少據我在3.1中可以看到的)不會設置標題。你工作的第二個版本是正確的(以及我總是實現添加標題的過濾器)!

    +0

    感謝您的回覆。在閱讀spec 3.0的文檔後,我剛剛進行了更改,文檔與您引用的文檔相同。 愚蠢的代碼註釋如何使用'doFilter'方法的混淆描述,儘管... –

    3

    甲骨文告訴你向下傳遞鏈之前包裹的反應,如果你想後

    注意補充一點,如果你要預處理請求對象或後處理 響應對象,你不能直接操縱原始的 請求或響應對象。你必須使用包裝。例如,在後處理 響應中,例如,目標servlet已經完成,並且響應可能已經在過濾器 有機會對響應執行任何操作時提交。 您必須通過 響應包裝,而不是鏈接 doFilter()調用中的原始響應。請參閱「使用過濾器包裝和更改請求或 響應」。

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

    相關問題