1. 程式人生 > >【javaweb】Session原理以及瀏覽器禁止Cookie之後伺服器如何獲取Session

【javaweb】Session原理以及瀏覽器禁止Cookie之後伺服器如何獲取Session

在web應用中開啟瀏覽器訪問一個網站,登入,瀏覽,到關閉瀏覽器,稱為是一個會話。由於Http協議是無狀態的,因此使用者在動態頁面互動資訊需要一些能夠儲存使用者資訊的資料結構。這個儲存使用者瀏覽資料的資料結構有兩種,一種是Cookie,儲存在客戶端;一種是Session,儲存在伺服器端。Session可以在瀏覽器最後一次訪問之後儲存30分鐘,當然這個值也是可以在web.xml檔案中配置的,Session的銷燬一方面可以是30分鐘內沒有再次訪問,另一方面可以是手動的銷燬。30分鐘無訪問就將Session銷燬時由於Session存在於伺服器端,會佔用伺服器的資源,因此超時銷燬是很必要的。

儲存在客戶端的Cookie可以設定有效期,在有效期內瀏覽器攜帶響應路徑下的Cookie訪問伺服器,伺服器就可以獲取使用者之前的訪問資訊了。Session本質上是基於Cookie的,由於當伺服器為瀏覽器建立Session之後會為每一個Session設定一個唯一的ID,用於區分不同訪問者。這個SessionID就通過Cookie的形式傳送給瀏覽器,之後每次瀏覽器訪問伺服器指定路徑的資源的時候就會帶著這個Cookie,伺服器根據Cookie總的ID找到先前建立的Session,然後從Session中獲取資料。

但是這個向瀏覽器寫資料的Cookie是沒有設定有效期的,一旦當前瀏覽器關閉,那麼再次開啟瀏覽器訪問之前的網站,由於Cookie失效了,伺服器端的Session即使是生命週期還沒結束也是無法獲取和使用的。

解決辦法是自己生成一個Cookie將Session的ID寫入,然後將寫入了SessionID的且設定了有效期的Cookie寫回給瀏覽器

建立:

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// 瀏覽器訪問的時候使用getSession()為其建立Session
		HttpSession session = request.getSession();

		String sessionID = session.getId();
		// Session的ID名稱為JSESSIONID,可以通過HTTPWatch檢視
		Cookie cookie = new Cookie("JSESSIONID", sessionID);
		cookie.setPath("/curpath");  // 設定cookie的路徑
		cookie.setMaxAge(30 * 60); // 設定的有效時間長度是session的存在時間 半個小時
		response.addCookie(cookie);
		session.setAttribute("mydata", "hello world");

	}

獲取:

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		HttpSession session = request.getSession(false); // 只獲取不建立
		String data = null;
		if(session != null) // 判斷是否獲取了Session
			data = (String) session.getAttribute("mydata");
		
<span style="white-space:pre">		</span>// Servlet中解決亂碼
		response.setCharacterEncoding("UTF-8");
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter pwriter = response.getWriter();
		
		pwriter.write("獲取的資料是: " + data);
	}

另外一種無法使用已經存在的Session的情形是使用者瀏覽器將Cookie禁止了,那麼Session的ID自然是無法傳送給瀏覽器,進而也就沒辦法繼續使用Session了。

解決這種問題可以採用URL重寫的方式,每次點選連結的時候瀏覽器都會講Session的ID傳送給伺服器,伺服器就取用相應的Session並獲取資訊。但是在重寫URL之前一定要先獲取Session。

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		response.setCharacterEncoding("UTF-8");
		response.setContentType("text/html;charset=UTF-8");
		
		PrintWriter pwriter = response.getWriter();
<span style="white-space:pre">		</span>// 在進行URL重寫的時候必須先建立Session
		request.getSession(); 
		
		// 然後重寫URL,將Session的ID以URL的形式傳遞給伺服器
		// 以解決使用者瀏覽器禁止Cookie導致的Session無法獲取的問題
		String url1 = response.encodeURL("/curpath/servlet/SessionDemo01");
		String url2 = response.encodeURL("/curpath/servlet/SessionDemo02");
		pwriter.write("<a href = '" + url1 + "'>傳送</a><br/>");
		pwriter.write("<a href = '" + url2 + "'>接收</a><br/>");

	}

當然兩種方法是可以一起使用的,getSession()方法會依次對從Cookie和URL中獲取SessionID,而且如果Cookie沒有被禁用,那麼就不會再將SessionID追加到URL上。

兩篇深入講解Session原理的博文:

http://ywj-316.iteye.com/blog/722941

http://www.cnblogs.com/wangtao_20/archive/2011/02/16/1955659.html