1. 程式人生 > >Filter過濾器實現自動登入

Filter過濾器實現自動登入

Filter介紹
問題:Filter是什麼,它能做什麼?
    1.從兩個方面來解析Filter是什麼?
       1.功能  可以幫助我們對請求與響應操作進行過濾。
       2.技術  Sun公司定義的一個介面,javax.servlet.Filter

   2.Filter能完成什麼操作?
       常用示例:
       1.通用編碼過濾器.
       2.粗粒度的許可權控制(url級別)
       3.過濾一些敏感字

Filter建立步驟:
        1.建立一個類實現javax.servlet.Filter介面。
        2.重寫Filter介面中三個方法  init  doFilter  destroy.
        3.在web.xml檔案中配置Filter

為什麼在web.xml檔案中配置Filter?
        1.Filter也是一個資源,也要被伺服器載入,所以要在web.xml檔案中配置.

        2.我們在web.xml檔案中配置Filter的另一個目的是用來設定Filter攔截什麼資源。

例項:需求:網站登入的時候當用戶勾選自動登入選框之後,當用戶再來登入,自動登入進網站。

      準備:簡單的模擬如下頁面:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title></title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	  </head>
  <body>
    <h3>這裡是最美網</h3>
	    <c:if test="${ not empty existUser}">	    
	    	<h2>歡迎您:${existUser.nickname }</h2>
	    </c:if>
	    <c:if test="${empty existUser }">
	    	<a href="${pageContext.request.contextPath }/login.jsp">請登入</a>
	    </c:if>
    <h3>新聞標題</h3>
    <h2>大閱兵</h2>
  </body>
</html>

    
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title></title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	  </head>
  <body>
  <form action="${pageContext.request.contextPath }/login" method="post">
	    <p style="color:red">${msg }</p>
	    使用者名稱:<input type="text" id="username" name = "username"><br>
	    密碼:<input type="password" id="password" name="password"><br>
	    <input type="checkbox" name="autologin" value="auto_ok">自動登入<br>
	    <button type="submit" value="登入">登入</button>
    </form>
  </body>
</html>

過濾器:

public class myFilter implements Filter {

	public void destroy() {
		
	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		
		/**
		 * 從session中獲取existUser
		 * 如果不為空,說明已經登入並且沒有關閉瀏覽器,放行
		 * 如果為空說明沒有登入,獲取指定名稱的cookie
		 *   *如果找不到該cookie說明使用者沒有開啟自動登入功能 ,放行
		 *   *如果不為空,從cookie中拿到使用者名稱和密碼從資料庫中查詢
		 *    *如果查不到 ,則使用者名稱或密碼改變了,不處理  放行
		 *    *如果查到了放到session中,放行
		 * 
		 */
		
		//從session中獲取使用者existUser
		HttpServletRequest req =(HttpServletRequest) request ;
		HttpSession session = req.getSession();
		User existUser  =(User) session.getAttribute("existUser");
		
		if (existUser!=null) {
			
			chain.doFilter(req, response);
			
		}else {
			//為空,說明沒有登入
			//獲取指定cookie
			//獲取儲存cookie的陣列
		    Cookie []cookies =	req.getCookies();
		    
		    Cookie cookie =MyCookieUtile.findCookieByName(cookies, "autologin");
		    
		    //判斷cookie是否為空
		    if (cookie==null) {
		    	
		    	chain.doFilter(req, response);
				
			}else{
				
				//獲取cookie的value值
				String value = cookie.getValue();
				String username = value.split(":")[0];
				String password = value.split(":")[1];
				
				//拿到cookie中的使用者名稱和密碼去資料庫中查
				UserDao dao = new UserDao();
				
				try {
					User user = dao.checkUser(username, password);
					
					if (user==null) {
						chain.doFilter(req, response);
					}else{
						//說明成功,自動登入
						session.setAttribute("existUser",user);
						//放行
						chain.doFilter(req, response);
						
					}
					
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}   		        
		    
		}
		
	}

	public void init(FilterConfig filterConfig) throws ServletException {
		
	}

}
public class MyCookieUtile {
	
	/**
	 * 通過傳入的cookie名稱從傳入的cookie陣列中查詢cookie
	 * 如果陣列為空,則沒有找到返回為null
	 * 如果不為空,找到返回cookie
	 * @param cookies
	 * @param cookiename
	 * @return
	 */	
	public static Cookie findCookieByName(Cookie []cookies,String cookiename){
		
		if (cookies==null) {
			return null;			
		}else{	
			
			for (Cookie cookie : cookies) {
				//獲取cookie的名稱和傳入的名稱對比
				if (cookiename.equals(cookie.getName()) ) {
					//相同則返回
					return cookie;					
				}
			}
			return null;
		}				
	}
}

servlet:

public class LoginServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		/**
		 * 接收引數
		 * 根據使用者名稱和密碼查詢資料庫
		 * 如果成功,返回到content頁
		 * 如果不成功,返回登入頁繼續登入
		 */
		//解決中文亂碼問題
		request.setCharacterEncoding("UTF-8");		
		String username = request.getParameter("username");
		String password = request.getParameter("password");		
		//呼叫dao層查詢
		UserDao dao = new UserDao();
		try {
			User existUser = dao.checkUser( username, password);
			
			if (existUser==null) {
				request.setAttribute("msg", "使用者名稱或密碼錯誤");
				request.getRequestDispatcher("/login.jsp").forward(request, response);
				
			}else{
				//登入成功
				
				//回寫cookie
				String autologin = request.getParameter("autologin");
				
				if ("auto_ok".equals(autologin)) {
					
					String value = username+":"+password;
					Cookie cookie = new Cookie("autologin", value);					
					//設定有效時間
					cookie.setMaxAge(60*60);
					//設定有效路徑
					cookie.setPath("/");					
					//回寫到客戶端
					response.addCookie(cookie);		
					
				}				
				request.getSession().setAttribute("existUser", existUser);				
				
				//重定向到content頁面
				response.sendRedirect(request.getContextPath()+"/content.jsp");
				
			}				
			
		} catch (SQLException e) {
			e.printStackTrace();
		}		
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doGet(request, response);

	}
}

         最後在配置檔案中web.xml檔案中配置filter。這樣當用戶勾選了自動登入,關閉瀏覽器之後,再次訪問即可自動登入進網站。

      在我們建立一個Filter時,要重寫介面中的方法,有一個方法doFilter,它就是用於攔截操作的方法。在配置Filter時,可以指定攔截什麼資源,當瀏覽器訪問這個資源時,Filter的doFilter方法就會執行攔截操作。

      我們如果在Filter中,它的doFilter方法執行了,代表攔截操作開始了,如果想要讓其可以繼續向下訪問資源,就需要通過doFilter方法的第三個引數FilterChain型別,呼叫它的doFilter方法,完成向下執行操作。

      總結:

   1.在Filter中具體的攔截操作是由doFilter方法執行的。  如果要想訪問資源,需要chain.doFilter()放行.
   2.攔截什麼資源是由web.xml檔案中配置的Filter確定的。