2012-10-29 99 views
2

我想實現一個過濾器來執行身份驗證,但不知何故它被卡住在無限循環中......任何想法都會被讚賞。Java Filter無限循環

HttpServletRequest httpRequest = (HttpServletRequest) request; 
    HttpServletResponse httpResponse = (HttpServletResponse) response; 

    doBeforeProcessing(request, response); 

    Throwable problem = null; 
    HttpSession session = httpRequest.getSession(true); 
    if(session.getAttribute("userName")!=null&&session.getAttribute("userName")!=("")) 
    { 
     try { 
      chain.doFilter(request, response); 
     } catch (Throwable t) { 
      // If an exception is thrown somewhere down the filter chain, 
      // we still want to execute our after processing, and then 
      // rethrow the problem after that. 
      problem = t; 
      t.printStackTrace(); 
     } 
    }else{ 
     httpResponse.sendRedirect("login.jsp"); 
     return; 
    } 

這段代碼在調試模式只是在無限的時間運行,basicly我希望將用戶重定向到的login.jsp時未登錄他。 任何答覆讚賞。

+0

這是過濾器也對'login.jsp'運行頁? – doublesharp

+0

是的,不幸的。無論如何,我提出了一個解決方案: 「如果(uri.indexOf(」 login.jsp的「)> - 1){ \t \t \t chain.doFilter(請求,響應); //只要繼續鏈 \t \t \t返回; \t \t}「 – czupe

+0

或者是否有更優雅的方式從過濾中排除login.jsp?我想在web.xml中的一些行,但據我所知它不支持這標記或類似此功能:( – czupe

回答

10

這裏,

httpResponse.sendRedirect("login.jsp"); 

你發送目標頁面的HTTP請求,而不是使用它的當前請求。如果這個新的HTTP請求被映射到過於通用的URL模式(例如/*),那麼當然會再次觸發過濾器。同樣的檢查將被執行,並且將被重新定向。等等。這是一個永無止境的故事。

當您請求的頁面是登錄頁面時,您還需要添加額外的檢查以執行FilterChain#doFilter()

String loginURL = httpRequest.getContextPath() + "/login.jsp"; 

if (httpRequest.getRequestURI().equals(loginURL)) || session.getAttribute("userName") != null) { 
    chain.doFilter(request, response); 
} else { 
    httpResponse.sendRedirect(loginURL); 
} 

請注意,我還取消了對空字符串作爲用戶名nonsensicial檢查(但是你會確保你的代碼無處被設置爲空字符串作爲用戶名。只需使用null表示一個非登錄另外請注意,我修復了重定向網址,因爲如果當前請求的URL位於子文件夾中,它會失敗。

另一種替代方法是將所有受限制的頁面放在公共子文件夾中,例如如/app,/secured, /restricted等,然後將過濾器映射到URL模式/app/*/secured/*/restricted/*等。如果您將登錄頁面保留在該文件夾之外,則在請求登錄頁面時不會調用該過濾器。

4

問題是您的過濾器運行在login.jsp上,並且當用戶未登錄時會反覆重定向到自己。因爲在過濾器上沒有排斥語法url-pattern你將需要檢測的URL在你的過濾器,並省略重定向,如果你已經在login.jsp頁:

// your auth code 
} else { 
    String redirect = httpRequest.getContextPath() + "/login.jsp"; 
    String uri = httpRequest.getRequestURI().toString(); 
    if (uri.endsWith(redirect)){ 
     // URI ends with login.jsp, just process the chain 
     chain.doFilter(); 
    } else { 
     // not on the login page and not logged in, redirect 
     httpResponse.sendRedirect(redirect); 
     return; 
    } 
} 
+0

謝謝你doublesharp,我投票了你的解決方案(和基本上我們在評論部分討論的額外的getContextPaath()和endsWith()函數)...是很難接受只有一個,但BalusC爲我提供了一些新的信息(因爲我看到的速度更快......)再次感謝doublesharp! – czupe

+1

總是投票贊成更多的信息和更快的執行:) – doublesharp