天天看點

cookie和session詳解1、Cookie機制2、Session機制3、Cookie和Session的差別

源自:https://www.cnblogs.com/l199616j/p/11195667.html,有删減。

另,cookie、session與token的真正差別:https://blog.csdn.net/whl190412/article/details/90024671

會話(Session)跟蹤是Web程式中常用的技術,用來跟蹤使用者的整個會話。常用的會話跟蹤技術是Cookie與Session。Cookie通過在用戶端記錄資訊确定使用者身份,Session通過在伺服器端記錄資訊确定使用者身份。

本章将系統地講述Cookie與Session機制,并比較說明什麼時候不能用Cookie,什麼時候不能用Session。

1、Cookie機制

​ Web應用程式是使用HTTP協定傳輸資料的。HTTP協定是無狀态的協定。一旦資料交換完畢,用戶端與伺服器端的連接配接就會關閉,再次交換資料需要建立新的連接配接。這就意味着伺服器無法從連接配接上跟蹤會話。即使用者A購買了一件商品放入購物車内,當再次購買商品時伺服器已經無法判斷該購買行為是屬于使用者A的會話還是使用者B的會話了。要跟蹤該會話,必須引入一種機制。

Cookie就是這樣的一種機制。它可以彌補HTTP協定無狀态的不足。在Session出現之前,基本上所有的網站都采用Cookie來跟蹤會話。

1.1、什麼是Cookie

​ 由于HTTP是一種無狀态的協定,伺服器單從網絡連接配接上無從知道客戶身份。怎麼辦呢?就給用戶端們頒發一個通行證吧,每人一個,無論誰通路都必須攜帶自己通行證。這樣伺服器就能從通行證上确認客戶身份了。這就是Cookie的工作原理。

​ 檢視某個網站頒發的Cookie很簡單。在浏覽器位址欄輸入**javascript:alert (document. cookie)**就可以了(需要有網才能檢視)。

​ 注意:Cookie功能需要浏覽器的支援。

1.2、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做了特殊處理。本章後面也會對Cookie做類似的處理。

1.3、Unicode編碼:儲存中文

中文與英文字元不同,中文屬于Unicode字元,在記憶體中占4個字元,而英文屬于ASCII字元,記憶體中隻占2個位元組。Cookie中使用Unicode字元時需要對Unicode字元進行編碼,否則會亂碼。

提示:Cookie中儲存中文隻能編碼。一般使用UTF-8編碼即可。不推薦使用GBK等中文編碼,因為浏覽器不一定支援,而且JavaScript也不支援GBK編碼。

1.4、BASE64編碼:儲存二進制圖檔

​ Cookie不僅可以使用ASCII字元與Unicode字元,還可以使用二進制資料。例如在Cookie中使用數字證書,提供安全度。使用二進制資料時也需要進行編碼。

注意:本程式僅用于展示Cookie中可以存儲二進制内容,并不實用。由于浏覽器每次請求伺服器都會攜帶Cookie,是以Cookie内容不宜過多,否則影響速度。Cookie的内容應該少而精。

1.5、設定Cookie的所有屬性

除了name與value之外,Cookie還具有其他幾個常用的屬性。每個屬性對應一個getter方法與一個setter方法。Cookie類的所有屬性如表1.1所示。

表1.1 Cookie常用屬性

屬 性 名 描 述
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,如果設定為true,那麼浏覽器隻會在HTTPS和SSL等安全協定中傳輸此類Cookie。

提示:secure屬性并不能對Cookie内容加密,因而不能保證絕對的安全性。如果需要高安全性,需要在程式中對Cookie内容加密、解密,以防洩密。

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規範

2、Session機制

除了使用Cookie,Web應用程式中還經常使用Session來記錄用戶端狀态。Session是伺服器端使用的一種記錄用戶端狀态的機制,使用上比Cookie簡單一些,相應的也增加了伺服器的存儲壓力。

2.1、什麼是Session

​ Session是另一種記錄客戶狀态的機制,不同的是Cookie儲存在用戶端浏覽器中,而Session儲存在伺服器上。用戶端浏覽器通路伺服器的時候,伺服器把用戶端資訊以某種形式記錄在伺服器上。這就是Session。用戶端浏覽器再次通路時隻需要從該Session中查找該客戶的狀态就可以了。Session對象是在用戶端第一次請求伺服器的時候建立的。

如果說Cookie機制是通過檢查客戶身上的“通行證”來确定客戶身份的話,那麼Session機制就是通過檢查伺服器上的“客戶明細表”來确認客戶身份。Session相當于程式在伺服器上建立的一份客戶檔案,客戶來訪的時候隻需要查詢客戶檔案表就可以了。

​ 當多個用戶端執行程式時,伺服器會儲存多個用戶端的Session。擷取Session的時候也不需要聲明擷取誰的Session。Session機制決定了目前客戶隻會擷取到自己的Session,而不會擷取到别人的Session。各客戶的Session也彼此獨立,互不可見。

提示**:Session的使用比Cookie友善,但是過多的Session存儲在伺服器記憶體中,會對伺服器造成壓力。**

2.2、Session的生命周期

Session儲存在伺服器端。為了獲得更高的存取速度,伺服器一般把Session放在記憶體裡。每個使用者都會有一個獨立的Session。如果Session内容過于複雜,當大量客戶通路伺服器時可能會導緻記憶體溢出。是以,Session裡的資訊應該盡量精簡。

Session在使用者第一次通路伺服器的時候自動建立。需要注意隻有通路JSP、Servlet等程式時才會建立Session,隻通路HTML、IMAGE等靜态資源并不會建立Session。如果尚未生成Session,也可以使用request.getSession(true)強制生成Session。

Session生成後,隻要使用者繼續通路,伺服器就會更新Session的最後通路時間,并維護該Session。使用者每通路伺服器一次,無論是否讀寫Session,伺服器都認為該使用者的Session“活躍(active)”了一次。

2.3、Session的有效期

由于會有越來越多的使用者通路伺服器,是以Session也會越來越多。為防止記憶體溢出,伺服器會把長時間内沒有活躍的Session從記憶體删除。這個時間就是Session的逾時時間。如果超過了逾時時間沒通路過伺服器,Session就自動失效了。

Session的逾時時間為maxInactiveInterval屬性,可以通過對應的getMaxInactiveInterval()擷取,通過setMaxInactiveInterval(longinterval)修改。

Session的逾時時間也可以在web.xml中修改。另外,通過調用Session的invalidate()方法可以使Session失效。

2.4、Session的常用方法

Session中包括各種方法,使用起來要比Cookie友善得多。Session的常用方法如表1.2所示。

表1.2 HttpSession的常用方法

方 法 名 描 述
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失效

2.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位址重寫。

2.6、URL位址重寫

URL位址重寫是對用戶端不支援Cookie的解決方案。URL位址重寫的原理是将該使用者Session的id資訊重寫到URL位址中。伺服器能夠解析重寫後的URL擷取Session的id。這樣即使用戶端不支援Cookie,也可以使用Session來記錄使用者狀态。

HttpServletResponse類提供了encodeURL(Stringurl)實作URL位址重寫

注意:TOMCAT判斷用戶端浏覽器是否支援Cookie的依據是請求中是否含有Cookie。盡管用戶端可能會支援Cookie,但是由于第一次請求時不會攜帶任何Cookie(因為并無任何Cookie可以攜帶),URL位址重寫後的位址中仍然會帶有jsessionid。當第二次通路時伺服器已經在浏覽器中寫入Cookie了,是以URL位址重寫後的位址中就不會帶有jsessionid了。

2.7、Session中禁止使用Cookie

既然WAP上大部分的客戶浏覽器都不支援Cookie,索性禁止Session使用Cookie,統一使用URL位址重寫會更好一些。Java Web規範支援通過配置的方式禁用Cookie。

下面舉例說一下怎樣通過配置禁止使用Cookie。

打開項目sessionWeb的WebRoot目錄下的META-INF檔案夾(跟WEB-INF檔案夾同級,如果沒有則建立),打開context.xml(如果沒有則建立),編輯内容如下:

/META-INF/context.xml

<?xml version='1.0' encoding='UTF-8'?>

<Context path="/sessionWeb"cookies="false">

</Context>
           

或者修改Tomcat全局的conf/context.xml,修改内容如下:

context.xml

<!-- The contents of this file will be loaded for eachweb application -->

<Context cookies="false">

    <!-- ... 中間代碼略 -->

</Context>
           

部署後TOMCAT便不會自動生成名JSESSIONID的Cookie,Session也不會以Cookie為識别标志,而僅僅以重寫後的URL位址為識别标志了。

注意:該配置隻是禁止Session使用Cookie作為識别标志,并不能阻止其他的Cookie讀寫。也就是說伺服器不會自動維護名為JSESSIONID的Cookie了,但是程式中仍然可以讀寫其他的Cookie。

3、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功能 ,預設設定為關閉;

一定要設定失效時間,要不然浏覽器關閉就消失了;

例如:

​ 記住密碼功能就是使用永久cookie寫在用戶端電腦,下次登入時,自動将cookie資訊附加發送給服務端。

​ application是全局性資訊,是所有使用者共享的資訊,如可以記錄有多少使用者現在登入過本網站,并把該資訊展示給所有使用者。

兩者最大的差別在于生存周期,一個是IE啟動到IE關閉.(浏覽器頁面一關 ,session就消失了),一個是預先設定的生存周期,或永久的儲存于本地的檔案。(cookie)

Session資訊是存放在server端,但session id是存放在client cookie的,當然php的session存放方法是多樣化的,這樣就算禁用cookie一樣可以跟蹤

Cookie是完全保持在用戶端的如:IE firefox 當用戶端禁止cookie時将不能再使用

繼續閱讀