天天看點

Java web-Cookie與Session1.會話技術

1.會話技術

1.1.概述

用戶端為了實作某一功能,發生了多次的請求響應,從用戶端開始通路伺服器開始,到通路結束,這期間産生的多次請求響應加在一起稱之為一個會話。

1.2.會話中的問題

每個使用者在使用浏覽器與伺服器進行會話的過程中,不可避免各自會産生一些資料,程式要想辦法為每個使用者儲存這些資料。

如使用者登入過後,應該儲存一個使用者狀态,在會話結束前表明使用者一直是登入狀态。并且不同的使用者之間的登入狀态應該互不影響。

我們之前已經學過request域和SerlvetContext域,我們分别分析一下。

Request域太小了,在多次請求中,每次請求響應都是新的Request對象,之前存入的request域中的域屬性,在請求結束後随着request域的銷毀而消失了。

ServletContext域太大了,所有使用者都在操作這個域,必然會發生混亂。

此時我們需要會話相關的技術,儲存會話産生的資料。

Cookie

cookie的原理是利用Set-cookie響應頭和cookie請求頭

cookie将會話産生的資料儲存在了用戶端中,是用戶端技術。

Session

session将會話産生的資料儲存在了伺服器端,是伺服器端的技術

1.3.Cookie

1.3.1.概述

Cookie是用戶端技術,程式把每個使用者的資料以cookie的形式寫給使用者各自的浏覽器。當使用者使用浏覽器再去通路伺服器中的web資源時,就會帶着各自的資料去。這樣,web資源處理的就是使用者各自的資料了。如圖-9所示:

Java web-Cookie與Session1.會話技術

cookie是會話相關的技術,可以儲存會話産生的資料,用戶端技術,将資料儲存在用戶端,基于set-Cookie響應頭和Cookie請求頭工作的.

1.3.2.Cookie常用方法

Cookie cookie = new Cookie(String name,String value);
--javax.servlet.http.Cookie類用于建立一個Cookie
setValue與getValue方法
--設定和擷取cookie的值
	getName方法
--cookie需要在建立時就指定好名字,這個名字一旦指定就不能修改了,如果需要修改隻能重新建立一個cookie
setMaxAge與getMaxAge方法  
--一個cookie被發送到浏覽器時,如果沒有設定過MaxAge,這個cookie将會被儲存在浏覽器的記憶體中,會一直存在到浏覽器關閉記憶體銷毀為止,這樣的cookie叫做會話級别的Cookie
--我們也可以使用setMaxAge方法設定cookie的存活時間,這樣一來,浏覽器收到這個Cookie資訊時會将cookie資訊以檔案的形式儲存在浏覽器的臨時檔案夾中,儲存到指定的時間到來位置,在這個期間即使多次開關浏覽器,cookie資訊一直都在.
 
setPath與getPath方法
--設定浏覽器在通路哪個位址及其子位址時,帶着cookie資訊過來.如果沒設定過,那麼預設的path是目前發送cookie的Servlet所在的路徑
 
setDomain與getDomain方法 
--設定浏覽器在通路哪個域名時,帶着目前的cookie,預設值目前發送cookie的域名,注意,現代的浏覽器隻要發現cookie設定過maxage,則認為這個cookie是第三方cookie,會拒絕接受      

1.3.3.發送cookie

response.addCookie(Cookie c);//向響應中增加一個cookie,可以在一次響應中增加多個cookie

1.3.4.擷取cookie

Cookie [] cs = request.getCookies();//傳回請求中所有cookike資訊組成的數組,如果請求中沒有任何cookie資訊此方法傳回null

1.3.5.删除cookie

        浏覽器是通過 名字+path+domain來區分cookie,如果發現cookie具有了相同的名字、path和domain時,cookie會發生覆寫。

        是以如果想要删除一個cookie,隻要發送一個同名 同path 的cookie,但是maxAge設定為0,覆寫掉要删除的cookie,覆寫過後,新的cookie立即逾時,被浏覽器删除,感覺起來就好像舊的cookie被删除了一樣。

1.3.6.cookie細節

一個Cookie隻能辨別一種資訊,它至少含有一個辨別該資訊的名稱(NAME)和設定值(VALUE)。

一個WEB站點可以給一個WEB浏覽器發送多個Cookie,一個WEB浏覽器也可以存儲多個WEB站點提供的Cookie。

浏覽器一般隻允許存放300個Cookie,每個站點最多存放20個Cookie,每個Cookie的大小限制為4KB。

如果建立了一個cookie,并将他發送到浏覽器,預設情況下它是一個會話級别的cookie(即存儲在浏覽器的記憶體中),使用者退出浏覽器之後即被删除。若希望浏覽器将該cookie存儲在磁盤上,則需要使用maxAge,并給出一個以秒為機關的時間。将最大時效設為0則是指令浏覽器删除該cookie。

注意,删除cookie時,path必須一緻,否則不會删除(浏覽器通過cookie的name+path來辨別一個cookie)

案例:實作記住使用者名功能

功能分析

如果使用者在登入時勾選了記住使用者名,則應該将使用者名稱使用者名儲存起來,在使用者下次登入時,讀取儲存的使用者名,顯示出來。

如果用Session儲存,我們知道,Session一旦30分鐘不使用就會失效,這個時間顯然太短了。

而用Cookie儲存,可以設定MaxAge指定儲存的時常,直到指定時間結束或使用者手動清楚cookie之前,此資訊一直存在。

是以我們選擇Cookie來實作儲存使用者名的功能。

代碼實作

在使用者登入的Servlet中,當使用者登入成功後,判斷使用者是否勾選過記住使用者名,如果使用者勾選過,則發送cookie儲存使用者名,注意MaxAge設定為30天。

//查詢資料庫是否存在指定使用者名密碼的使用者
try {
	SAXReader reader = new SAXReader();
	Document dom = reader.read(this.getServletContext().getRealPath("WEB-INF/classes/users.xml"));
	Element root = dom.getRootElement();
	Element ele = (Element) root.selectSingleNode(
"//user[@username='"+username+"' and @password='"+password+"']"
);
	if(ele == null){
		//沒有找到,提示使用者名密碼不正确
		response.getWriter().write("使用者名密碼不正确!");
		return;
	}else{
		//使用者名密碼正确,将使用者名儲存到session中表明使用者登入過
		request.getSession().setAttribute("user", username);
		//檢查使用者是否勾選過記住使用者名
		if("true".equals(request.getParameter("remname"))){
			//發送cookie儲存使用者名
				Cookie remnamec = new Cookie("remname",username);
			remnamec.setPath("/");
			remnamec.setMaxAge(3600*24*30);
			response.addCookie(remnamec);
		}
		//回到首頁
		response.sendRedirect("/index.jsp");
	}
} catch (Exception e) {
	e.printStackTrace();
	throw new RuntimeException(e);
}      

1.4.Session

1.4.1.概述

Session是伺服器端技術,利用這個技術,伺服器在運作時可以為每一個使用者的浏覽器建立一個其獨享的session對象,由于session為使用者浏覽器獨享,是以使用者在通路伺服器的web資源時,可以把各自的資料放在各自的session中,當使用者再去通路伺服器中的其它web資源時,其它web資源再從使用者各自的session中取出資料為使用者服務。

Java web-Cookie與Session1.會話技術

1.4.2.Session是一個域對象

生命周期:

當程式第一次調用到request.getSession()代碼時,伺服器明确的直到了需要用到session了,此時建立session.

如果session超過30分鐘(可以在web.xml中配置的)沒人使用,伺服器認為這個session逾時了,銷毀session.

明确的調用session.invalidate(),session立即銷毀.

伺服器被非正常關閉或web應用被移除出容器,此時随着web應用的銷毀session銷毀.如果是正常關閉,session會被鈍化.當下次伺服器正常啟動時,沒有逾時的session還會被活化回來.

作用範圍:

整個會話範圍内可見

主要作用:

在會話範圍内共享資料

1.4.3.實作登入功能

1.4.3.1.登入原理

所謂的登入,就是要将登入過後的使用者狀态儲存起來,在後續的請求中能夠獲知這種狀态,這就是典型的在會話中儲存資料的過程。

我們可以在Session中儲存一個登入标記,表明目前使用者已經登入過。後續需要時隻需檢查Session中的該标記即可判斷出使用者是否登入過

1.4.3.2.代碼實作

在Servlet我們擷取使用者送出的使用者名密碼
//解決請求亂碼
request.setCharacterEncoding("utf-8");
//解決響應亂碼
response.setContentType("text/html;charset=utf-8");
 
//擷取使用者送出的使用者名 密碼
	String username = request.getParameter("username");
String password = request.getParameter("password");
通過查詢資料庫檢查使用者名密碼是否正确,如果不正确則進行提示,如果正确則在Session中儲存使用者的登入狀态後回到首頁
//查詢資料庫是否存在指定使用者名密碼的使用者
try {
SAXReader reader = new SAXReader();
Document dom = reader.read(this.getServletContext().getRealPath("WEB-INF/classes/users.xml"));
	Element root = dom.getRootElement();
Element ele = (Element) root.selectSingleNode("//user[@username='"+username+"' and @password='"+password+"']");
	if(ele == null){
		//沒有找到,提示使用者名密碼不正确
		response.getWriter().write("使用者名密碼不正确!");
		return;
	}else{
		//使用者名密碼正确,将使用者名儲存到session中表明使用者登入過
		request.getSession().setAttribute("user", username);
		//回到首頁
		response.sendRedirect("/index.jsp");
	}
	} catch (Exception e) {
		e.printStackTrace();
		throw new RuntimeException(e);
}      

1.4.4.實作防止表單重複送出

1.4.4.1.表單重複送出概述

當網絡延遲等情況發生時,使用者無法确定表單是否已經送出,進而多次點選送出,造成資料多次送出,稱為發生了表單重複送出。

真實案例:12306網站購票

1.4.4.2.防止表單重複送出

生成一個令牌。

在session域中儲存令牌。

在表單中隐藏字段儲存令牌。

當表單送出時,在處理的Servlet裡檢查,如果送出的令牌和session中儲存的令牌一緻,則執行邏輯,并删除session中的令牌。

如果session域中沒有令牌,或和送出的令牌不符合,則認為是表單重複送出,提示

1.4.4.3.代碼實作

jsp中代碼

Java web-Cookie與Session1.會話技術

java中代碼

Java web-Cookie與Session1.會話技術

1.4.5.實作驗證碼

驗證碼送出後該如何進行校驗呢?應該在使用者擷取驗證碼時,将驗證碼資訊存入session域,在使用者送出表單時,将使用者送出的驗證碼和session中儲存的驗證碼進行比較,如果一緻,則驗證碼正确。

ValiImgServlet,如圖:

Java web-Cookie與Session1.會話技術

RegistServlet,如圖:

Java web-Cookie與Session1.會話技術

regist.jsp,如圖:

Java web-Cookie與Session1.會話技術

cookie和session比較:

cookie是用戶端的技術,會話産生的資料儲存在用戶端。session是伺服器端的技術,會話産生的資料儲存在伺服器端。

cookie資訊可以儲存的時間比較長。但是安全性不高。可能随着使用者的操作cookie會被清空,資料穩定性比較差。是以cookie适合存放要儲存的時間比較長,安全性要求不高,丢失也無所謂的資訊。

session資訊儲存的時間通常比較有限。但是安全性高,并且在session存活期間,資料一直存在穩定性很高,不會因為使用者的操作導緻session中資料以外丢失。是以session适合存放資料安全性穩定性要求比較高,但是不需要長時間儲存的資料。

1.5.URL編碼

1.5.1.概述

其實這種編碼方式我們見過,當我們用浏覽器送出中文資料時,中文資料也是經過URL編碼後送出的。對于非iso8859-1的字元,浏覽器和伺服器預設使用URL編碼進行處理。

浏覽器和伺服器之間是通過HTTP協定通信的

HTTP協定隻支援ISO8859-1字元集 

是以其實從理論上來說 HTTP協定隻能處理 ISO8859-1中具有的字元 不能進行中文

怎麼解決HTTP協定攜帶中文的問題呢? -- URL編碼

通過URL編碼 用戶端将非iso8859-1的字元轉換為 URL編碼形式 發送給伺服器 伺服器收到後再進行URL解碼 就可以轉換回原來的字元了

1.5.2.URL編解碼

Java中提供了進行URL編碼和解碼的類
URLEncoder:static String encode(String s,String enc);
//将指定的字元串按照指定的編碼轉換為URL編碼的形式
URLDecoder:static String decode(String s,String enc);
//将URL編碼後的字元串按照指定編碼解碼為源字元串      

案例:對cookie進行中文處理

改造代碼,在發送cookie時,進行URL編碼
//檢查使用者是否勾選過記住使用者名
if("true".equals(request.getParameter("remname"))){
	//發送cookie儲存使用者名
Cookie remnamec = 
new Cookie("remname",URLEncoder.encode(username, "utf-8"));
	remnamec.setPath("/");
	remnamec.setMaxAge(3600*24*30);
	response.addCookie(remnamec);
}      

jsp中,使用者名要經過URL解碼

Java web-Cookie與Session1.會話技術
Java web-Cookie與Session1.會話技術

繼續閱讀