Cookie和Session都是為了保持用戶的訪問狀態,一方面為了方便業務實現,另一方面為了簡化服務端的程序設計,提高訪問性能。Cookie是客戶端(也就是瀏覽器端)的技術,設置了Cookie之后,每次訪問服務端,請求中都會帶上Cookie;Session是服務端技術,在服務端存儲用戶的訪問信息。
使用Cookie傳遞信息,隨著Cookie個數增多和訪問量增大,它占用的帶寬會越來越大;使用Session保存信息,最大的弱點就是不容易在多臺服務器之間共享。
1 Cookie
通俗地講,當用戶使用HTTP訪問服務器時,服務器會將一些鍵值對信息返回給客戶端瀏覽器,并且給這些數據加一些限制條件,在符合限制條件情況下用戶下次訪問服務器時,會帶上之前設置的Cookie鍵值對信息。當該用戶輸入 URL 時,瀏覽器便會在本地硬盤上查找與該 URL 關聯的 Cookie。如果該 Cookie 存在,瀏覽器便將該 Cookie 與頁請求一起發送到您的站點。
Cookie 與網站關聯,而不是與特定的頁面關聯。因此,無論用戶請求站點中的哪一個頁面,瀏覽器和服務器都將交換 Cookie 信息。用戶訪問不同站點時,各個站點都可能會向用戶的瀏覽器發送一個 Cookie;瀏覽器會分別存儲所有 Cookie。
Cookie屬性項
當前Cookie有2個版本,Version 0 和 Version 1,它們有2種設置響應頭標識,分別是"Set-Cookie"和"Set-Cookie2"。
Cookie 0屬性值
Cookie 1屬性值
Java中使用Cookie示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
@Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setContentType( "text/html;charset=utf-8" ); PrintWriter out = response.getWriter(); Cookie[] cookies = request.getCookies(); String name = getCoodie(cookies, "name" ); if (name == null ) { response.addCookie( new Cookie( "name" , "luoxn28" )); } else { System.out.println(name); } out.println( "hello world" ); } public static String getCoodie(Cookie[] cookies, String key) { if (cookies != null ) { for (Cookie cookie : cookies) { if (cookie.getName().equals(key)) { return cookie.getValue(); } } } return null ; } |
使用Cookie的一些注意事項(以Java使用為例)
•所創建的Cookie的name和value不能為非ASSIC字符,如果是中文,可以通過RRLEncoder將其編碼,否則會拋出java.lang.IllegalArgumentException異常。
•多出現多個name和value值時,它們實在同一個"Cookie"頭中的。
•Cookies的值中可以保存除了“;”以外的標點符號。但是不能保存漢字。保存漢字會出現亂碼。
Cookie的一些限制
Cookie是HTTP頭中的一個字段,HTTP本身對該字段沒有限制,但是Cookie最終存儲在瀏覽器中,不同的瀏覽器對Cookie的存儲有一些限制,如下表所示:
如果試圖存儲更多 Cookie,則最舊的 Cookie 便會被丟棄。
2 Session
Session解決了Cookie增多時會增加客戶端與服務器的數據傳輸量問題,同一個客戶端與服務器交互時,不需要每次都傳回所有的Cookie值,而是只要傳回一個ID值,這個ID是客戶端第一次訪問服務器時生成的,而且每個客戶端是唯一的,這個ID通常是name為JSESSIONID的一個Cookie。
Session是如何基于Cookie工作的呢,可以是基于URL Path Parameter方式;也可以是基于Cookie,如果沒有修改Context容器中的Cookies標識,則默認也是支持的。當瀏覽器不支持Cookie功能時,瀏覽器會將用戶的SessionCookieName重寫到用戶請求的URL參數中,它的傳遞方式如/path/Servlet;name=xxx;name2=xxx2?name3=xxx3。SessionCookieName如果在web.xml中配置session-config配置項,其cookie-config下的name屬性就是這個SessionCookieName的值。如果沒有配置session-config配置項,默認的SessionCookieNamejiushi “JSESSIONID”。注意,與Session關聯的Cookie與其他Cookie并沒有什么不同。如果客戶端也支持Cookie,則Tomcat仍會解析Cookie中的Session ID,并會覆蓋URL中的Session ID。
Session如何工作
有了Session ID,服務器就可以創建HttpSession對象了,第一次調用request.getSession()方法,如果沒有對應的HttpSession對象,則會創建一個新的,并將這個對象加入到org.apache.catalina.Manager的sessions容器中保存。Manage保存所有的session生命周期,Session過期被回收,服務器關閉,Session被序列化到磁盤。注意,一個客戶端對應一個Session對象,這個對象正是保存我們創建的Session值的。
request.getSession()方法調用的StandardSession永遠都會存在,即使與這個客戶端關聯的Session已經過期。如果過期,則會創建一個新的,但是以前設置的Session值將會丟失。
3 Cookie與Session安全性比較
Cookie將保存的數據通過HTTP頭部從客戶端傳到服務端,從服務端再傳回到客戶端,所有的數據都保存在客戶端瀏覽器中,這些數據都是可以訪問到的,甚至可以通過插件添加、修改Cookie,所有Cookie的安全性是比較差的。相比較而言,Session將數據保存在服務器端,安全性高很多,只需要Cookie傳回一個Cookie ID就可以,所以Session更適合保存用戶隱私和重要的數據。
分布式Session框架
在大型互聯網應用中,單用Cookie和Session都是不可行的,因為如果使用Cookie可以很好地解決應用的分布式部署問題,大型互聯網應用系統一個應用有上百臺機器,而且有很多不同的應用系統協同工作,由于Cookie是將數據存儲在用戶瀏覽器中,用戶每次訪問都會講數據帶回到服務器,也就解決了同一個用戶的請求在不同服務器上處理而導致的Cookie不一致問題。
由于應用是一個集群,所以不能將Session都保存在每臺服務器的內存中,如果每臺服務器有幾十萬訪問用戶,服務器內存也容不下,即使容得下,也無法保證該Session同步到其他服務器中,所以共享這些Session需要將它們保存在專門的分布式緩存中,可以隨時讀取和寫入,性能要夠好滿足要求,如memcache/redis或者淘寶的開源分布式框架Tair都是很好的選擇。
表單重復提交問題
網站中有很多地方有重復提交表單問題,為了防止表單重復提交,就要標識用戶的每一次訪問請求,使得每一次訪問請求對服務端來說都是唯一的,為了標識用戶的每次請求,可以在用戶請求的表單域增加一個隱藏表單項,其值為唯一的token,如:
1
2
3
4
|
<form id= "form" method= "post" > ... <input type=hidden name= "token" value= "xxx" /> </form> |
用戶請求表單時生成唯一的token,并且設置到該用戶的Session中,等用戶提交時檢測這個token是否和Session中保存的token一致,如果一致,說明沒有重復提交,同時把Session中的token更新成一個新的token值;否則用戶提交上來的token已經不是當前請求的合法token,提交失敗。
以上所述是小編給大家介紹的Java中Cookie和Session的那些事兒,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!
原文鏈接:http://www.cnblogs.com/luoxn28/p/5894557.html