標籤:使用 generated gets 過濾 reg addm pat web應用 做了
最近在看過濾器,剛剛實現了過濾器的簡化認證功能:
使用過濾器簡化認證:
在Web應用程式中,過濾器的一個關鍵用例是保護應用程式不被未授權的使用者訪問。為跨國組件公司開發的客戶支援應用程式使用了一種非常原始的認證機制保護頁面。你可能已經注意到應用程式中的許多地方都包含了相同的重複代碼,用於檢查認證:
1 if (request.getSession().getAttribute("userName") == null){2 response.sendRedirect("login");3 return; 4 }
同時你可能認為認證更簡單的方式就是在某個類上建立一個公開靜態方法執行該檢查,並在所有的地方調用它。確實,這將減少重複代碼,但它仍然會導致在多個地方調用該方法的問題。隨著應用程式中,Servlet數量的增加,同樣也會增加對該靜態方法的調用。
所以過濾器對簡化認證還是很有用處的,我做了一個小小的demo,思路是,調用listServlet,listServlet中重新導向到index.jsp,當然我在webListener中動態配置Filter的時候就是對路徑"/index.jsp"頁面配置的。所以在跳轉到index.jsp頁面之前,會執行過濾器中的代碼(判斷是否已經登入,登入狀態允許跳轉到index.jsp,非登入狀態將重新導向到login.jsp讓使用者登入).
接下來是listServlet(我直接進入這個servlet開啟整個demo的測試)
import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@WebServlet(name="listServlet",urlPatterns="/list")public class listServlet extends HttpServlet { /** * */ private static final long serialVersionUID = 1L; @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("listServet"); resp.sendRedirect(req.getServletContext().getContextPath() + "/index.jsp"); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); }}
這是對應的過濾器AuthenticationFilter
import java.io.IOException;import java.time.Instant;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.annotation.WebFilter;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;public class AuthenticationFilter implements Filter{ @Override public void destroy() { // TODO Auto-generated method stub } @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {if (req.getAttribute("userName") == null) { ((HttpServletResponse)resp).sendRedirect(req.getServletContext().getContextPath() + "/login.jsp"); }else{ chain.doFilter(req, resp); } } @Override public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub }}
在web監聽器中,會配置相應的過濾器
1 package deep.web.listener; 2 3 import java.util.Collection; 4 5 import javax.servlet.FilterRegistration; 6 import javax.servlet.ServletContext; 7 import javax.servlet.ServletContextEvent; 8 import javax.servlet.ServletContextListener; 9 import javax.servlet.annotation.WebListener;10 11 import deep.web.filter.AuthenticationFilter;12 13 @WebListener14 public class Configurator implements ServletContextListener{15 16 @Override17 public void contextDestroyed(ServletContextEvent arg0) {18 // TODO Auto-generated method stub19 20 }21 22 @Override23 public void contextInitialized(ServletContextEvent event) {24 ServletContext context = event.getServletContext();25 26 FilterRegistration.Dynamic registration = context.addFilter("authenticationFilter", new AuthenticationFilter());27 28 registration.setAsyncSupported(true);29 System.out.println("contextInitialized");30 31 registration.addMappingForUrlPatterns(null, false, "/index.jsp");32 33 /*這是我測試用的,判斷是否配置好了url,並且輸出url*/34 System.out.println(registration.getUrlPatternMappings().isEmpty());35 Collection<String> str = registration.getUrlPatternMappings();36 System.out.println(str);37 }38 39 }
我把loginServlet也粘貼出來吧
1 package deep.web.controller; 2 3 import java.io.IOException; 4 5 import javax.servlet.ServletException; 6 import javax.servlet.annotation.WebServlet; 7 import javax.servlet.http.HttpServlet; 8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse;10 11 12 @WebServlet(name="userServlet",urlPatterns="/user")13 public class userServlet extends HttpServlet{14 private static final long serialVersionUID = 1L;15 @Override16 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {17 18 }19 @Override20 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {21 System.out.println("userServlet");22 String method= req.getParameter("method");23 if (method.equals("login")) {24 System.out.println("loginServlet");25 String name = req.getParameter("name");26 String password = req.getParameter("password");27 if (name.equals("test") && password.equals("test")) {28 req.getSession().setAttribute("userName","name" );29 resp.sendRedirect(req.getServletContext().getContextPath() + "/list.jsp");30 }else{31 System.out.println("登入失敗~");32 resp.sendRedirect(req.getServletContext().getContextPath() + "/login.jsp");33 }34 }35 }36 }
接下來是輸出結果,我會直接進入listServlet→進入過濾器(如果已經登入)→進入index.jsp
→進入過濾器(如果沒有登入)→進入login.jsp
採用這種方式的優勢在於:如果要修改認證演算法,只需要修改過濾器就可以保護應用程式中的資源。之前,你將不得不修改所有的Servlet。
其實不應該用request來認證,應該用session,額,腦瓜子疼...sorry
參考書籍:《Java Web進階編程》
java過濾器(簡化認證)