基於的過濾器的登入驗證
阿新 • • 發佈:2018-11-08
問題背景
目前系統使用的基於攔截器Interceptor的登入驗證似乎出了些問題,有些情況下在Controller層獲取session中的使用者資料時失敗。具體原因沒有找到,組長說應該是Interceptor這塊出了些問題,於是打算將登入驗證放到Filter上去做。
基本業務邏輯
1 判斷請求url是否需要進行登入驗證;
2 如果需要登入驗證,則判斷是否有登入的使用者資料,否則執行過濾器鏈中的下一個過濾器;
3 如果使用者未登入,轉跳到登陸頁;否則執行過濾器鏈中的下一個過濾器
堆程式碼
package com.shtd.common.filter; import java.io.IOException; import java.util.regex.Pattern; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.lang3.StringUtils; import org.springframework.web.filter.OncePerRequestFilter; import com.shtd.common.util.LoginConstants; import com.shtd.modules.edu.roll.entity.vo.StuUser; public class LoginFilter extends OncePerRequestFilter{ private String excludedPages; private String[] excludedPageArray; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // System.out.println(" ==登入過濾==" + request.getServletPath()); HttpSession session = request.getSession(); StuUser curUser = (StuUser)session.getAttribute(LoginConstants.SESSION_KEY_CURUSER); if (curUser == null || curUser.getId() == null){ // System.out.println(" ==未通過=="); response.sendRedirect(request.getContextPath()+ "/login"); } else { // System.out.println(" ==通過=="); filterChain.doFilter(request, response); } } /** * 初始化時獲得引數 */ @Override protected void initFilterBean() throws ServletException { // System.out.println("初始化 登入過濾器"); excludedPages = getFilterConfig().getInitParameter("exclusions"); if (StringUtils.isNotEmpty(excludedPages)) { excludedPageArray = excludedPages.split(","); for (int i=0; i < excludedPageArray.length; i++) { String excludedPage = excludedPageArray[i]; if (excludedPage.contains("**")){ StringBuilder builder = new StringBuilder(); builder.append("^"); builder.append(StringUtils.replace(excludedPage, "**", "\\S*")); builder.append("$"); excludedPageArray[i] = builder.toString(); } // System.out.println(excludedPageArray[i]); } } } /** * 是否要跳過過濾器 */ protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { if (excludedPageArray == null || excludedPageArray.length == 0) { return false; } String path = request.getServletPath(); for (String excludedPage : excludedPageArray) { if (StringUtils.isBlank(excludedPage)) { continue; } if (excludedPage.startsWith("^")){ if (Pattern.matches(excludedPage, path)) { return true; } } else if (excludedPage.equals(path)) { return true; } } return false; } }
配置檔案
<!-- 登入狀態過濾 --> <filter> <filter-name>loginFilter</filter-name> <filter-class>com.shtd.common.filter.LoginFilter</filter-class> <init-param> <param-name>exclusions</param-name> <param-value>/login,/init-pwd,/authenticate,/resources/**</param-value> </init-param> </filter> <filter-mapping> <filter-name>loginFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 登入狀態過濾, 結束-->
值得注意的點
1 Filter沒有類似於Interceptor的exclude-mapping的設定——嚴重覺得可能是我沒找到——只能通過init-param來傳入要忽略的路徑;
2 一般情況下,實現javax.servlet.Filter就行了,然後我發現繼承spring的OncePerRequestFilter會更方便一些。它將init和destroy方法都封裝好了,我們只需要關注於doFilter這塊。同時也提供和獲得傳入引數和是否需要進入過濾器的判斷方法,只要重寫相應的方法就行了
3 記得通過過濾後,執行filterChain.doFilter(request, response);