源自: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時将不能再使用