Disable JSESSIONID URL Rewriting in JSF

最近在工作上用 JSF 寫程式時,發現如果用 <h:outputLink /> 這個 tag 來輸出 <a href=”xxxx” /> 之類的連結,在瀏覽器首次瀏覽時,JSF 產生的連結會自動將 jsessionid 附在 URL 的後面。

例如下圖,我用 <h:outputLink value=”#{bundle[‘link.hinet’]}” /> 產生一個 Hinet 的連結(link.hinet 定義於 ResourceBundle 中)。首次執行時,可以看出在 Hinet 連結後面 JSF 自動幫忙加上了 jsessionid 的參數。

如果目的地不是一個 J2EE Web 應用程式,直接點下去,很容易會出現 404 Not Found 的錯誤訊息。

初步猜想應該是首次瀏覽時,JSF 針對 jsessionid 做了 URL Rewriting。因為首次瀏覽時,JSF 還不知道瀏覽器是否有將 Cookie enable,所以除了嘗試要將 jsessionid 設定到 Cookie 之外,另外在 URL 上面也針對 session id 做了一次重寫,以便保證 session 可以傳遞到下一個動作。

實際驗證的結果,在首次瀏覽之後,再將 URL 中的 jsessionid 參數移除,在功能上也是完全不受影響,因此我可以確認應該是這個問題。找了很久,從書上跟 Google 找來找去,似乎也沒看到 JSF 上有可以將這個自動重寫機制關掉的參數。所以看起來只能從 J2EE Web Context 來想辦法了。

從 Google 上找到了一篇文章 禁用JavaWeb應用中URL上包含的jsessionid ,裡面提到的方式就是先繼承 HttpServletResponse,實作一個自己的 HttpServletResponseWrapper,並且將所有相關的 encodeUrl 函式全部改寫,直接回傳 URL,不再加以處理。再搭配 Filter 來處理每一個 Request / Response。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

public void doFilter(ServletRequest request, ServletResponse response,
		FilterChain chain) throws IOException, ServletException {
	// TODO Auto-generated method stub
	if (!(request instanceof HttpServletRequest)) {  
           chain.doFilter(request, response);  
		return;  
	}  

	HttpServletRequest httpRequest = (HttpServletRequest) request;  
	HttpServletResponse httpResponse = (HttpServletResponse) response;  		
	if (httpRequest.isRequestedSessionIdFromURL()) {  
	    HttpSession session = httpRequest.getSession();  
		if (session != null) session.invalidate();  
	}  		
	
	HttpServletResponseWrapper wrappedResponse  
	    = new HttpServletResponseWrapper(httpResponse) 
	{  
	    public String encodeRedirectUrl(String url) { return url; }  
	    public String encodeRedirectURL(String url) { return url; }  
	    public String encodeUrl(String url) { return url; }  
	    public String encodeURL(String url) { return url; }  
	 };
	 
	 chain.doFilter(request, wrappedResponse);
}

所以後續 JSF 呼叫 encodeUrl 來進行 rewriting 時,自然 jsessionid 也不會被加上去了。

實際部署後,果然首次瀏覽時,URL 就不會再出現 jsessionid 了。不過如此的結果就是 Client 端必須啟動 Cookie 了。

下載 DisableUrlSessionFilter.java

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料