cookie 和 session 详解
cookie 和 session 詳解
文章目錄
- cookie 和 session 詳解
- 一、Cookie機制
- 1.Cookie引入
- 2.什么是Cookie
- 3.Cookie的不可跨域名性
- 4. Unicode編碼:保存中文
- 5. BASE64編碼:保存二進制圖片
- 6.設置Cookie的所有屬性
- 7. Cookie的有效期
- 8. Cookie的修改、刪除
- 9. Cookie的域名
- 10. Cookie的路徑
- 11. Cookie的安全屬性
- 二、什么是Session
- 1.Session
- 2.Session的生命周期
- 3.Session的有效期
- 4.Session的常用方法
- 5.Session對瀏覽器的要求
- 6.URL地址重寫
- 三、cookie和session的區別總結
- 四、HTTP 請求的完整流程
會話(Session)跟蹤是Web程序中常用的技術,用來跟蹤用戶的整個會話。常用的會話跟蹤技術是Cookie與Session。Cookie通過在客戶端記錄信息確定用戶身份,Session通過在服務器端記錄信息確定用戶身份。
一、Cookie機制
1.Cookie引入
- 在程序中,會話跟蹤是很重要的事情。理論上,一個用戶的所有請求操作都應該屬于同一個會話,而另一個用戶的所有請求操作則應該屬于另一個會話,二者不能混淆。
- 例如,用戶A在超市購買的任何商品都應該放在A的購物車內,不論是用戶A什么時間購買的,這都是屬于同一個會話的,不能放入用戶B或用戶C的購物車內,這不屬于同一個會話。
- 而Web應用程序是使用HTTP協議傳輸數據的。
- HTTP協議是無狀態的協議。一旦數據交換完畢,客戶端與服務器端的連接就會關閉,再次交換數據需要建立新的連接。這就意味著服務器無法從連接上跟蹤會話。
- 即用戶A購買了一件商品放入購物車內,當再次購買商品時服務器已經無法判斷該購買行為是屬于用戶A的會話還是用戶B的會話了。要跟蹤該會話,必須引入一種機制。
- Cookie就是這樣的一種機制。它可以彌補HTTP協議無狀態的不足。在Session出現之前,基本上所有的網站都采用Cookie來跟蹤會話。
2.什么是Cookie
- Cookie意為“甜餅”,是由W3C組織提出,最早由Netscape社區發展的一種機制。目前Cookie已經成為標準,所有的主流瀏覽器如IE、Netscape、Firefox、Opera等都支持Cookie。
- 由于HTTP是一種無狀態的協議,服務器單從網絡連接上無從知道客戶身份。
- 怎么辦呢?就給客戶端們頒發一個通行證吧,每人一個,無論誰訪問都必須攜帶自己通行證。這樣服務器就能從通行證上確認客戶身份了。這就是Cookie的工作原理。
- Cookie實際上是一小段的文本信息。一個 cookie 可以認為是一個「變量」,形如name=value鍵值對的形式存儲在瀏覽器;
- 客戶端請求服務器,如果服務器需要記錄該用戶狀態,就使用response向客戶端瀏覽器頒發一個Cookie。客戶端瀏覽器會把Cookie保存起來。
- 當瀏覽器再請求該網站時,瀏覽器把請求的網址連同該Cookie一同提交給服務器。服務器檢查該Cookie,以此來辨認用戶狀態。服務器還可以根據需要修改Cookie的內容。
- 查看某個網站頒發的Cookie很簡單。在瀏覽器地址欄輸入javascript:alert (document. cookie)就可以了
注意:Cookie功能需要瀏覽器的支持。
如果瀏覽器不支持Cookie(如大部分手機中的瀏覽器)或者把Cookie禁用了,Cookie功能就會失效。
不同的瀏覽器采用不同的方式保存Cookie。
IE瀏覽器會在“C:\Documents and
Settings\你的用戶名\Cookies”文件夾下以文本文件形式保存,一個文本文件保存一個Cookie。
3.Cookie的不可跨域名性
- 很多網站都會使用Cookie。例如,Google會向客戶端頒發Cookie,Baidu也會向客戶端頒發Cookie。那瀏覽器訪問Google會不會也攜帶上Baidu頒發的Cookie呢?或者Google能不能修改Baidu頒發的Cookie呢?
- 答案是否定的。Cookie具有不可跨域名性。根據Cookie規范,瀏覽器訪問Google只會攜帶Google的Cookie,而不會攜帶Baidu的Cookie。Google也只能操作Google的Cookie,而不能操作Baidu的Cookie。
- Cookie在客戶端是由瀏覽器來管理的。瀏覽器能夠保證Google只會操作Google的Cookie而不會操作Baidu的Cookie,從而保證用戶的隱私安全。
- 瀏覽器判斷一個網站是否能操作另一個網站Cookie的依據是域名。Google與Baidu的域名不一樣,因此Google不能操作Baidu的Cookie。
需要注意的是,雖然網站images.google.com與網站www.google.com同屬于Google,但是域名不一樣,二者同樣不能互相操作彼此的Cookie。
注意:用戶登錄網站www.google.com之后會發現訪問images.google.com時登錄信息仍然有效,而普通的Cookie是做不到的。這是因為Google做了特殊處理。
4. Unicode編碼:保存中文
- 中文與英文字符不同,中文屬于Unicode字符,在內存中占4個字符,而英文屬于ASCII字符,內存中只占2個字節。Cookie中使用Unicode字符時需要對Unicode字符進行編碼,否則會亂碼。
提示:Cookie中保存中文只能編碼。一般使用UTF-8編碼即可。不推薦使用GBK等中文編碼,因為瀏覽器不一定支持,而且JavaScript也不支持GBK編碼。
5. BASE64編碼:保存二進制圖片
- Cookie不僅可以使用ASCII字符與Unicode字符,還可以使用二進制數據。
- 例如在Cookie中使用數字證書,提供安全度。使用二進制數據時也需要進行編碼。
注意:Cookie中可以存儲二進制內容,并不實用。由于瀏覽器每次請求服務器都會攜帶Cookie,因此Cookie內容不宜過多,否則影響速度。Cookie的內容應該少而精。
6.設置Cookie的所有屬性
- 除了name與value之外,Cookie還具有其他幾個常用的屬性。每個屬性對應一個getter方法與一個setter方法。
| String name | 該Cookie的名稱。Cookie一旦創建,名稱便不可更改 |
| Object value | 該Cookie的值。如果值為Unicode字符,需要為字符編碼。如果值為二進制數據,則需要使用BASE64編碼 |
| int maxAge | 該Cookie失效的時間,單位秒。如果為正數,則該Cookie在maxAge秒之后失效。如果為負數,該Cookie為臨時Cookie,關閉瀏覽器即失效,瀏覽器也不會以任何形式保存該Cookie。如果為0,表示刪除該Cookie。默認為–1 |
| boolean secure | 該Cookie是否僅被使用安全協議傳輸。安全協議。安全協議有HTTPS,SSL等,在網絡上傳輸數據之前先將數據加密。默認為false |
| String path | 該Cookie的使用路徑。如果設置為“/sessionWeb/”,則只有contextPath為“/sessionWeb”的程序可以訪問該Cookie。如果設置為“/”,則本域名下contextPath都可以訪問該Cookie。注意最后一個字符必須為“/” |
| String domain | 可以訪問該Cookie的域名。如果設置為“.google.com”,則所有以“google.com”結尾的域名都可以訪問該Cookie。注意第一個字符必須為“.” |
| String comment | 該Cookie的用處說明。瀏覽器顯示Cookie信息的時候顯示該說明 |
| int version | 該Cookie使用的版本號。0表示遵循Netscape的Cookie規范,1表示遵循W3C的RFC 2109規范 |
7. Cookie的有效期
- Cookie的maxAge決定著Cookie的有效期,單位為秒(Second)。
- Cookie中通過getMaxAge()方法與setMaxAge(int maxAge)方法來讀寫maxAge屬性。
- 如果maxAge屬性為正數,則表示該Cookie會在maxAge秒之后自動失效。瀏覽器會將maxAge為正數的Cookie持久化,即寫到對應的Cookie文件中。無論客戶關閉了瀏覽器還是電腦,只要還在maxAge秒之前,登錄網站時該Cookie仍然有效。
下面代碼中的Cookie信息將永遠有效。
Cookie cookie = new Cookie("username","helloweenvsfei"); // 新建Cookiecookie.setMaxAge(Integer.MAX_VALUE); // 設置生命周期為MAX_VALUEresponse.addCookie(cookie); // 輸出到客戶端- 如果maxAge為負數,則表示該Cookie僅在本瀏覽器窗口以及本窗口打開的子窗口內有效,關閉窗口后該Cookie即失效。
- maxAge為負數的Cookie,為臨時性Cookie,不會被持久化,不會被寫到Cookie文件中。Cookie信息保存在瀏覽器內存中,因此關閉瀏覽器該Cookie就消失了。Cookie默認的maxAge值為–1。
- 如果maxAge為0,則表示刪除該Cookie。Cookie機制沒有提供刪除Cookie的方法,因此通過設置該Cookie即時失效實現刪除Cookie的效果。失效的Cookie會被瀏覽器從Cookie文件或者內存中刪除,
例如:
Cookie cookie = new Cookie("username","helloweenvsfei"); // 新建Cookiecookie.setMaxAge(0); // 設置生命周期為0,不能為負數response.addCookie(cookie); // 必須執行這一句response對象提供的Cookie操作方法只有一個添加操作add(Cookie cookie)。
要想修改Cookie只能使用一個同名的Cookie來覆蓋原來的Cookie,達到修改的目的。刪除時只需要把maxAge修改為0即可。
注意:從客戶端讀取Cookie時,包括maxAge在內的其他屬性都是不可讀的,也不會被提交。瀏覽器提交Cookie時只會提交name與value屬性。maxAge屬性只被瀏覽器用來判斷Cookie是否過期。
8. Cookie的修改、刪除
- Cookie并不提供修改、刪除操作。如果要修改某個Cookie,只需要新建一個同名的Cookie,添加到response中覆蓋原來的Cookie。
- 如果要刪除某個Cookie,只需要新建一個同名的Cookie,并將maxAge設置為0,并添加到response中覆蓋原來的Cookie。
注意是0而不是負數。負數代表其他的意義。
注意:修改、刪除Cookie時,新建的Cookie除value、maxAge之外的所有屬性,例如name、path、domain等,都要與原Cookie完全一樣。
否則,瀏覽器將視為兩個不同的Cookie不予覆蓋,導致修改、刪除失敗。
9. Cookie的域名
- Cookie是不可跨域名的。
域名www.google.com頒發的Cookie不會被提交到域名www.baidu.com去。這是由Cookie的隱私安全機制決定的。隱私安全機制能夠禁止網站非法獲取其他網站的Cookie。
- 正常情況下,同一個一級域名下的兩個二級域名如www.helloweenvsfei.com和images.helloweenvsfei.com也不能交互使用Cookie,因為二者的域名并不嚴格相同。
如果想所有helloweenvsfei.com名下的二級域名都可以使用該Cookie,需要設置Cookie的domain參數,例如:
Cookie cookie = new Cookie("time","20080808"); // 新建Cookiecookie.setDomain(".helloweenvsfei.com"); // 設置域名cookie.setPath("/"); // 設置路徑cookie.setMaxAge(Integer.MAX_VALUE); // 設置有效期response.addCookie(cookie); // 輸出到客戶端可以修改本機C:\WINDOWS\system32\drivers\etc下的hosts文件來配置多個臨時域名,然后使用setCookie.jsp程序來設置跨域名Cookie驗證domain屬性。
注意:domain參數必須以點(".")開始。另外,name相同但domain不同的兩個Cookie是兩個不同的Cookie。如果想要兩個域名完全不同的網站共有Cookie,可以生成兩個Cookie,domain屬性分別為兩個域名,輸出到客戶端。
10. Cookie的路徑
- domain屬性決定運行訪問Cookie的域名,而path屬性決定允許訪問Cookie的路徑(ContextPath)
例如,如果只允許/sessionWeb/下的程序使用Cookie,可以這么寫:
設置為“/”時允許所有路徑使用Cookie。path屬性需要使用符號“/”結尾。name相同但domain相同的兩個Cookie也是兩個不同的Cookie。
注意:頁面只能獲取它屬于的Path的Cookie。例如/session/test/a.jsp不能獲取到路徑為/session/abc/的Cookie。使用時一定要注意。
11. Cookie的安全屬性
- HTTP協議不僅是無狀態的,而且是不安全的。使用HTTP協議的數據不經過任何加密就直接在網絡上傳播,有被截獲的可能。使用HTTP協議傳輸很機密的內容是一種隱患。
- 如果不希望Cookie在HTTP等非安全協議中傳輸,可以設置Cookie的secure屬性為true。瀏覽器只會在HTTPS和SSL等安全協議中傳輸此類Cookie。
下面的代碼設置secure屬性為true:
Cookie cookie = new Cookie("time", "20080808"); // 新建Cookiecookie.setSecure(true); // 設置安全屬性response.addCookie(cookie); // 輸出到客戶端提示:secure屬性并不能對Cookie內容加密,因而不能保證絕對的安全性。如果需要高安全性,需要在程序中對Cookie內容加密、解密,以防泄密。
二、什么是Session
1.Session
- 一個 session 可以理解為一種數據結構,多數情況是「映射」(鍵值對),存儲在服務器上
- session 是一個數據結構,由網站的開發者設計,所以可以承載各種數據,只要客戶端的 cookie 傳來一個唯一的 session ID,服務器就可以找到對應的 session,認出這個客戶。
- 當然,由于 session 存儲在服務器中,肯定會消耗服務器的資源,所以 session 一般都會有一個過期時間,服務器一般會定期檢查并刪除過期的 session,如果后來該用戶再次訪問服務器,可能就會面臨重新登錄等等措施,然后服務器新建一個 session,將 session ID 通過 cookie 的形式傳送給客戶端。
- Session是另一種記錄客戶狀態的機制,不同的是Cookie保存在客戶端瀏覽器中,而Session保存在服務器上。
- 客戶端瀏覽器訪問服務器的時候,服務器把客戶端信息以某種形式記錄在服務器上。這就是Session。
- 客戶端瀏覽器再次訪問時只需要從該Session中查找該客戶的狀態就可以了。
- 如果說Cookie機制是通過檢查客戶身上的“通行證”來確定客戶身份的話,那么Session機制就是通過檢查服務器上的“客戶明細表”來確認客戶身份。
- Session相當于程序在服務器上建立的一份客戶檔案,客戶來訪的時候只需要查詢客戶檔案表就可以了。
2.Session的生命周期
- Session保存在服務器端。為了獲得更高的存取速度,服務器一般把Session放在內存里。每個用戶都會有一個獨立的Session。
- 如果Session內容過于復雜,當大量客戶訪問服務器時可能會導致內存溢出。因此,Session里的信息應該盡量精簡。
Session在用戶第一次訪問服務器的時候自動創建。
Session生成后,只要用戶繼續訪問,服務器就會更新Session的最后訪問時間,并維護該Session。用戶每訪問服務器一次,無論是否讀寫Session,服務器都認為該用戶的Session“活躍(active)”了一次。
3.Session的有效期
- 由于會有越來越多的用戶訪問服務器,因此Session也會越來越多。為防止內存溢出,服務器會把長時間內沒有活躍的Session從內存刪除
- 這個時間就是Session的超時時間。如果超過了超時時間沒訪問過服務器,Session就自動失效了。
- Session的超時時間為maxInactiveInterval屬性,可以通過對應的getMaxInactiveInterval()獲取,通過setMaxInactiveInterval(longinterval)修改。
- Session的超時時間也可以在web.xml中修改。另外,通過調用Session的invalidate()方法可以使Session失效。
4.Session的常用方法
Session中包括各種方法,使用起來要比Cookie方便得多。
| void setAttribute(String attribute, Object value) | 設置Session屬性。value參數可以為任何Java Object。通常為Java Bean。value信息不宜過大 |
| String getAttribute(String attribute) | 返回Session屬性 |
| Enumeration getAttributeNames() | 返回Session中存在的屬性名 |
| void removeAttribute(String attribute) | 移除Session屬性 |
| String getId() | 返回Session的ID。該ID由服務器自動創建,不會重復 |
| long getCreationTime() | 返回Session的創建日期。返回類型為long,常被轉化為Date類型,例如:Date createTime = new Date(session.get CreationTime()) |
| long getLastAccessedTime() | 返回Session的最后活躍時間。返回類型為long |
| int getMaxInactiveInterval() | 返回Session的超時時間。單位為秒。超過該時間沒有訪問,服務器認為該Session失效 |
| void setMaxInactiveInterval(int second) | 設置Session的超時時間。單位為秒 |
| void putValue(String attribute, Object value) | 不推薦的方法。已經被setAttribute(String attribute, Object Value)替代 |
| Object getValue(String attribute) | 不被推薦的方法。已經被getAttribute(String attr)替代 |
| boolean isNew() | 返回該Session是否是新創建的 |
| void invalidate() | 使該Session失效 |
- Tomcat中Session的默認超時時間為20分鐘。通過setMaxInactiveInterval(intseconds)修改超時時間。可以修改web.xml改變Session的默認超時時間。
例如修改為60分鐘:
<session-config><session-timeout>60</session-timeout> <!-- 單位:分鐘 --></session-config>注意:參數的單位為分鐘,而setMaxInactiveInterval(int s)單位為秒。
5.Session對瀏覽器的要求
- 雖然Session保存在服務器,對客戶端是透明的,它的正常運行仍然需要客戶端瀏覽器的支持。
- 這是因為Session需要使用Cookie作為識別標志。HTTP協議是無狀態的,Session不能依據HTTP連接來判斷是否為同一客戶
因此服務器向客戶端瀏覽器發送一個名為JSESSIONID的Cookie,它的值為該Session的id(也就是HttpSession.getId()的返回值)。Session依據該Cookie來識別是否為同一用戶。
該Cookie為服務器自動生成的,它的maxAge屬性一般為–1,表示僅當前瀏覽器內有效,并且各瀏覽器窗口間不共享,關閉瀏覽器就會失效。
- 因此同一機器的兩個瀏覽器窗口訪問服務器時,會生成兩個不同的Session。
但是由瀏覽器窗口內的鏈接、腳本等打開的新窗口(也就是說不是雙擊桌面瀏覽器圖標等打開的窗口)除外。這類子窗口會共享父窗口的Cookie,因此會共享一個Session。
- 注意:新開的瀏覽器窗口會生成新的Session,但子窗口除外。子窗口會共用父窗口的Session。
例如,在鏈接上右擊,在彈出的快捷菜單中選擇“在新窗口中打開”時,子窗口便可以訪問父窗口的Session。
如果客戶端瀏覽器將Cookie功能禁用,或者不支持Cookie怎么辦?例如,絕大多數的手機瀏覽器都不支持Cookie。Java
Web提供了另一種解決方案:URL地址重寫。
6.URL地址重寫
- URL地址重寫是對客戶端不支持Cookie的解決方案。
- URL地址重寫的原理是將該用戶Session的id信息重寫到URL地址中。服務器能夠解析重寫后的URL獲取Session的id。這樣即使客戶端不支持Cookie,也可以使用Session來記錄用戶狀態。
HttpServletResponse類提供了encodeURL(Stringurl)實現URL地址重寫,例如:
<td><a href="<%=response.encodeURL("index.jsp?c=1&wd=Java") %>"> Homepage</a></td>- 該方法會自動判斷客戶端是否支持Cookie。
- 如果客戶端支持Cookie,會將URL原封不動地輸出來。
- 如果客戶端不支持Cookie,則會將用戶Session的id重寫到URL中。
- 重寫后的輸出可能是這樣的:
即在文件名的后面,在URL參數的前面添加了字符串“;jsessionid=XXX”。其中XXX為Session的id。分析一下可以知道,增添的jsessionid字符串既不會影響請求的文件名,也不會影響提交的地址欄參數。用戶單擊這個鏈接的時候會把Session的id通過URL提交到服務器上,服務器通過解析URL地址獲得Session的id。
如果是頁面重定向(Redirection),URL地址重寫可以這樣寫:
<%if(“administrator”.equals(userName)){response.sendRedirect(response.encodeRedirectURL(“administrator.jsp”));return;}%>三、cookie和session的區別總結
-
1、cookie數據存放在客戶的瀏覽器上,session數據放在服務器上.
-
簡單的說,當你登錄一個網站的時候,如果web服務器端使用的是session,那么所有的數據都保存在服務器上面
-
客戶端每次請求服務器的時候會發送當前會話的session_id,服務器根據當前session_id判斷相應的用戶數據標志,以確定用戶是否登錄,或具有某種權限。
-
由于數據是存儲在服務器 上面,所以你不能偽造,但是如果你能夠獲取某個登錄用戶的session_id,用特殊的瀏覽器偽造該用戶的請求也是能夠成功的。
-
session_id是服務器和客戶端鏈接時候隨機分配的,一般來說是不會有重復,但如果有大量的并發請求,也不是沒有重復的可能性。
-
Session是由應用服務器維持的一個服務器端的存儲空間,用戶在連接服務器時,會由服務器生成一個唯一的SessionID,用該SessionID 為標識符來存取服務器端的Session存儲空間。
-
而SessionID這一數據則是保存到客戶端,用Cookie保存的,用戶提交頁面時,會將這一 SessionID提交到服務器端,來存取Session數據。這一過程,是不用開發人員干預的。所以一旦客戶端禁用Cookie,那么Session也會失效。
-
2、cookie不是很安全,別人可以分析存放在本地的COOKIE并進行COOKIE欺騙考慮到安全應當使用session。
-
3、設置cookie時間可以使cookie過期。但是使用session-destory(),我們將會銷毀會話。
-
4、session會在一定時間內保存在服務器上。當訪問增多,會比較占用你服務器的性能考慮到減輕服務器性能方面,應當使用cookie。
-
5、單個cookie保存的數據不能超過4K,很多瀏覽器都限制一個站點最多保存20個cookie。(Session對象沒有對存儲的數據量的限制,其中可以保存更為復雜的數據類型)
注意:
session很容易失效,用戶體驗很差;雖然cookie不安全,但是可以加密;cookie也分為永久和暫時存在的;瀏覽器 有禁止cookie功能 ,但一般用戶都不會設置;一定要設置失效時間,要不然瀏覽器關閉就消失了;所以個人建議:將登陸信息等重要信息存放為SESSION其他信息如果需要保留,可以放在COOKIE中四、HTTP 請求的完整流程
- 1、瀏覽器通過 HTTP 協議向服務器請求路徑/content的網頁資源,對應路徑上有一個 Handler 函數接收請求,解析 HTTP header 中的 cookie,得到其中存儲的 sessionID,然后把這個 ID 發給Manager。
- 2、Manager充當一個 session 管理器的角色,主要存儲一些配置信息,比如 session 的存活時間,cookie 的名字等等。而所有的 session 存在一個Provider中。所以Manager會把sid(sessionID)傳遞給Provider,讓它去找這個 ID 對應的具體是哪個 session。
- 3、Provider就是一個容器,最常見的應該就是一個散列表,將每個sid和對應的 session 一一映射起來。收到Manager傳遞的sid之后,它就找到sid對應的 session 結構,也就是Session結構,然后返回它。
- 4、Session中存儲著用戶的具體信息,一般是一個散列表,由 Handler 函數中的邏輯拿出這些信息,生成該用戶的 HTML網頁,返回給客戶端。
總結
以上是生活随笔為你收集整理的cookie 和 session 详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FastDFS安装与部署
- 下一篇: Git/SQL/正则表达式练习平台