Cookie與Session有何異同?

2021-03-13    分類: 網(wǎng)站建設

會話(Session)跟蹤是Web程序中常用的技術(shù),用來跟蹤用戶的整個會話。常用的會話跟蹤技術(shù)是Cookie與Session。Cookie通過在客戶端記錄信息確定用戶身份,Session通過在服務器端記錄信息確定用戶身份。

本章將系統(tǒng)地講述Cookie與Session機制,并比較說明什么時候不能用Cookie,什么時候不能用Session。

 

1.1  Cookie機制

在程序中,會話跟蹤是很重要的事情。理論上,一個用戶的所有請求操作都應該屬于同一個會話,而另一個用戶的所有請求操作則應該屬于另一個會話,二者不能混淆。例如,用戶A在超市購買的任何商品都應該放在A的購物車內(nèi),不論是用戶A什么時間購買的,這都是屬于同一個會話的,不能放入用戶B或用戶C的購物車內(nèi),這不屬于同一個會話。

而Web應用程序是使用HTTP協(xié)議傳輸數(shù)據(jù)的。HTTP協(xié)議是無狀態(tài)的協(xié)議。一旦數(shù)據(jù)交換完畢,客戶端與服務器端的連接就會關閉,再次交換數(shù)據(jù)需要建立新的連接。這就意味著服務器無法從連接上跟蹤會話。即用戶A購買了一件商品放入購物車內(nèi),當再次購買商品時服務器已經(jīng)無法判斷該購買行為是屬于用戶A的會話還是用戶B的會話了。要跟蹤該會話,必須引入一種機制。

Cookie就是這樣的一種機制。它可以彌補HTTP協(xié)議無狀態(tài)的不足。在Session出現(xiàn)之前,基本上所有的網(wǎng)站都采用Cookie來跟蹤會話。

1.1.1  什么是Cookie

Cookie意為“甜餅”,是由W3C組織提出,最早由Netscape社區(qū)發(fā)展的一種機制。目前Cookie已經(jīng)成為標準,所有的主流瀏覽器如IE、Netscape、Firefox、Opera等都支持Cookie。

由于HTTP是一種無狀態(tài)的協(xié)議,服務器單從網(wǎng)絡連接上無從知道客戶身份。怎么辦呢?就給客戶端們頒發(fā)一個通行證吧,每人一個,無論誰訪問都必須攜帶自己通行證。這樣服務器就能從通行證上確認客戶身份了。這就是Cookie的工作原理。

Cookie實際上是一小段的文本信息??蛻舳苏埱蠓掌?,如果服務器需要記錄該用戶狀態(tài),就使用response向客戶端瀏覽器頒發(fā)一個Cookie。客戶端瀏覽器會把Cookie保存起來。當瀏覽器再請求該網(wǎng)站時,瀏覽器把請求的網(wǎng)址連同該Cookie一同提交給服務器。服務器檢查該Cookie,以此來辨認用戶狀態(tài)。服務器還可以根據(jù)需要修改Cookie的內(nèi)容。

 

 

查看某個網(wǎng)站頒發(fā)的Cookie很簡單。在瀏覽器地址欄輸入javascript:alert (document. cookie)就可以了(需要有網(wǎng)才能查看)。JavaScript腳本會彈出一個對話框顯示本網(wǎng)站頒發(fā)的所有Cookie的內(nèi)容,如圖1.1所示。

圖1.1  Baidu網(wǎng)站頒發(fā)的Cookie

 

圖1.1中彈出的對話框中顯示的為Baidu網(wǎng)站的Cookie。其中第一行BAIDUID記錄的就是筆者的身份helloweenvsfei,只是Baidu使用特殊的方法將Cookie信息加密了。

 

注意:Cookie功能需要瀏覽器的支持。

如果瀏覽器不支持Cookie(如大部分手機中的瀏覽器)或者把Cookie禁用了,Cookie功能就會失效。

不同的瀏覽器采用不同的方式保存Cookie。

IE瀏覽器會在“C:\Documents and Settings\你的用戶名\Cookies”文件夾下以文本文件形式保存,一個文本文件保存一個Cookie。

 

1.1.2  記錄用戶訪問次數(shù)

Java中把Cookie封裝成了javax.servlet.http.Cookie類。每個Cookie都是該Cookie類的對象。服務器通過操作Cookie類對象對客戶端Cookie進行操作。通過request.getCookie()獲取客戶端提交的所有Cookie(以Cookie[]數(shù)組形式返回),通過response.addCookie(Cookiecookie)向客戶端設置Cookie。

Cookie對象使用key-value屬性對的形式保存用戶狀態(tài),一個Cookie對象保存一個屬性對,一個request或者response同時使用多個Cookie。因為Cookie類位于包javax.servlet.http.*下面,所以JSP中不需要import該類。

 

1.1.3  Cookie的不可跨域名性

很多網(wǎng)站都會使用Cookie。例如,Google會向客戶端頒發(fā)Cookie,Baidu也會向客戶端頒發(fā)Cookie。那瀏覽器訪問Google會不會也攜帶上Baidu頒發(fā)的Cookie呢?或者Google能不能修改Baidu頒發(fā)的Cookie呢?

答案是否定的。Cookie具有不可跨域名性。根據(jù)Cookie規(guī)范,瀏覽器訪問Google只會攜帶Google的Cookie,而不會攜帶Baidu的Cookie。Google也只能操作Google的Cookie,而不能操作Baidu的Cookie。

Cookie在客戶端是由瀏覽器來管理的。瀏覽器能夠保證Google只會操作Google的Cookie而不會操作Baidu的Cookie,從而保證用戶的隱私安全。瀏覽器判斷一個網(wǎng)站是否能操作另一個網(wǎng)站Cookie的依據(jù)是域名。Google與Baidu的域名不一樣,因此Google不能操作Baidu的Cookie。

需要注意的是,雖然網(wǎng)站images.google.com與網(wǎng)站www.google.com同屬于Google,但是域名不一樣,二者同樣不能互相操作彼此的Cookie。

 

注意:用戶登錄網(wǎng)站www.google.com之后會發(fā)現(xiàn)訪問images.google.com時登錄信息仍然有效,而普通的Cookie是做不到的。這是因為Google做了特殊處理。本章后面也會對Cookie做類似的處理。

 

1.1.4  Unicode編碼:保存中文

中文與英文字符不同,中文屬于Unicode字符,在內(nèi)存中占4個字符,而英文屬于ASCII字符,內(nèi)存中只占2個字節(jié)。Cookie中使用Unicode字符時需要對Unicode字符進行編碼,否則會亂碼。

 

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

 

1.1.5  BASE64編碼:保存二進制圖片

Cookie不僅可以使用ASCII字符與Unicode字符,還可以使用二進制數(shù)據(jù)。例如在Cookie中使用數(shù)字證書,提供安全度。使用二進制數(shù)據(jù)時也需要進行編碼。

%注意:本程序僅用于展示Cookie中可以存儲二進制內(nèi)容,并不實用。由于瀏覽器每次請求服務器都會攜帶Cookie,因此Cookie內(nèi)容不宜過多,否則影響速度。Cookie的內(nèi)容應該少而精。

 

1.1.6  設置Cookie的所有屬性

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

表1.1  Cookie常用屬性

屬  性  名

描    述

String name

該Cookie的名稱。Cookie一旦創(chuàng)建,名稱便不可更改

Object value

該Cookie的值。如果值為Unicode字符,需要為字符編碼。如果值為二進制數(shù)據(jù),則需要使用BASE64編碼

int maxAge

該Cookie失效的時間,單位秒。如果為正數(shù),則該Cookie在maxAge秒之后失效。如果為負數(shù),該Cookie為臨時Cookie,關閉瀏覽器即失效,瀏覽器也不會以任何形式保存該Cookie。如果為0,表示刪除該Cookie。默認為–1

boolean secure

該Cookie是否僅被使用安全協(xié)議傳輸。安全協(xié)議。安全協(xié)議有HTTPS,SSL等,在網(wǎng)絡上傳輸數(shù)據(jù)之前先將數(shù)據(jù)加密。默認為false

String path

該Cookie的使用路徑。如果設置為“/sessionWeb/”,則只有contextPath為“/sessionWeb”的程序可以訪問該Cookie。如果設置為“/”,則本域名下contextPath都可以訪問該Cookie。注意最后一個字符必須為“/”

String domain

可以訪問該Cookie的域名。如果設置為“.google.com”,則所有以“google.com”結(jié)尾的域名都可以訪問該Cookie。注意第一個字符必須為“.”

String comment

該Cookie的用處說明。瀏覽器顯示Cookie信息的時候顯示該說明

int version

該Cookie使用的版本號。0表示遵循Netscape的Cookie規(guī)范,1表示遵循W3C的RFC 2109規(guī)范

 

1.1.7  Cookie的有效期

Cookie的maxAge決定著Cookie的有效期,單位為秒(Second)。Cookie中通過getMaxAge()方法與setMaxAge(int maxAge)方法來讀寫maxAge屬性。

如果maxAge屬性為正數(shù),則表示該Cookie會在maxAge秒之后自動失效。瀏覽器會將maxAge為正數(shù)的Cookie持久化,即寫到對應的Cookie文件中。無論客戶關閉了瀏覽器還是電腦,只要還在maxAge秒之前,登錄網(wǎng)站時該Cookie仍然有效。下面代碼中的Cookie信息將永遠有效。

 

Cookie cookie = new Cookie("username","helloweenvsfei");   // 新建Cookie

cookie.setMaxAge(Integer.MAX_VALUE);           // 設置生命周期為MAX_VALUE

response.addCookie(cookie);                    // 輸出到客戶端

 

如果maxAge為負數(shù),則表示該Cookie僅在本瀏覽器窗口以及本窗口打開的子窗口內(nèi)有效,關閉窗口后該Cookie即失效。maxAge為負數(shù)的Cookie,為臨時性Cookie,不會被持久化,不會被寫到Cookie文件中。Cookie信息保存在瀏覽器內(nèi)存中,因此關閉瀏覽器該Cookie就消失了。Cookie默認的maxAge值為–1。

如果maxAge為0,則表示刪除該Cookie。Cookie機制沒有提供刪除Cookie的方法,因此通過設置該Cookie即時失效實現(xiàn)刪除Cookie的效果。失效的Cookie會被瀏覽器從Cookie文件或者內(nèi)存中刪除,

 

例如:

Cookie cookie = new Cookie("username","helloweenvsfei");   // 新建Cookie

cookie.setMaxAge(0);                          // 設置生命周期為0,不能為負數(shù)

response.addCookie(cookie);                    // 必須執(zhí)行這一句

 

response對象提供的Cookie操作方法只有一個添加操作add(Cookie cookie)。

要想修改Cookie只能使用一個同名的Cookie來覆蓋原來的Cookie,達到修改的目的。刪除時只需要把maxAge修改為0即可。

 

注意:從客戶端讀取Cookie時,包括maxAge在內(nèi)的其他屬性都是不可讀的,也不會被提交。瀏覽器提交Cookie時只會提交name與value屬性。maxAge屬性只被瀏覽器用來判斷Cookie是否過期。

 

1.1.8  Cookie的修改、刪除

Cookie并不提供修改、刪除操作。如果要修改某個Cookie,只需要新建一個同名的Cookie,添加到response中覆蓋原來的Cookie。

如果要刪除某個Cookie,只需要新建一個同名的Cookie,并將maxAge設置為0,并添加到response中覆蓋原來的Cookie。注意是0而不是負數(shù)。負數(shù)代表其他的意義。讀者可以通過上例的程序進行驗證,設置不同的屬性。

 

注意:修改、刪除Cookie時,新建的Cookie除value、maxAge之外的所有屬性,例如name、path、domain等,都要與原Cookie完全一樣。否則,瀏覽器將視為兩個不同的Cookie不予覆蓋,導致修改、刪除失敗。

 

1.1.9  Cookie的域名

Cookie是不可跨域名的。域名www.google.com頒發(fā)的Cookie不會被提交到域名www.baidu.com去。這是由Cookie的隱私安全機制決定的。隱私安全機制能夠禁止網(wǎng)站非法獲取其他網(wǎng)站的Cookie。

正常情況下,同一個一級域名下的兩個二級域名如www.helloweenvsfei.com和images.helloweenvsfei.com也不能交互使用Cookie,因為二者的域名并不嚴格相同。如果想所有helloweenvsfei.com名下的二級域名都可以使用該Cookie,需要設置Cookie的domain參數(shù),例如:

Cookie cookie = new Cookie("time","20080808"); // 新建Cookie

cookie.setDomain(".helloweenvsfei.com");           // 設置域名

cookie.setPath("/");                              // 設置路徑

cookie.setMaxAge(Integer.MAX_VALUE);               // 設置有效期

response.addCookie(cookie);                       // 輸出到客戶端

 

讀者可以修改本機C:\WINDOWS\system32\drivers\etc下的hosts文件來配置多個臨時域名,然后使用setCookie.jsp程序來設置跨域名Cookie驗證domain屬性。

注意:domain參數(shù)必須以點(".")開始。另外,name相同但domain不同的兩個Cookie是兩個不同的Cookie。如果想要兩個域名完全不同的網(wǎng)站共有Cookie,可以生成兩個Cookie,domain屬性分別為兩個域名,輸出到客戶端。

 

1.1.10  Cookie的路徑

domain屬性決定運行訪問Cookie的域名,而path屬性決定允許訪問Cookie的路徑(ContextPath)。例如,如果只允許/sessionWeb/下的程序使用Cookie,可以這么寫:

Cookie cookie = new Cookie("time","20080808");     // 新建Cookie

cookie.setPath("/session/");                          // 設置路徑

response.addCookie(cookie);                           // 輸出到客戶端

設置為“/”時允許所有路徑使用Cookie。path屬性需要使用符號“/”結(jié)尾。name相同但domain相同的兩個Cookie也是兩個不同的Cookie。

 

注意:頁面只能獲取它屬于的Path的Cookie。例如/session/test/a.jsp不能獲取到路徑為/session/abc/的Cookie。使用時一定要注意。

 

1.1.11  Cookie的安全屬性

HTTP協(xié)議不僅是無狀態(tài)的,而且是不安全的。使用HTTP協(xié)議的數(shù)據(jù)不經(jīng)過任何加密就直接在網(wǎng)絡上傳播,有被截獲的可能。使用HTTP協(xié)議傳輸很機密的內(nèi)容是一種隱患。如果不希望Cookie在HTTP等非安全協(xié)議中傳輸,可以設置Cookie的secure屬性為true。瀏覽器只會在HTTPS和SSL等安全協(xié)議中傳輸此類Cookie。下面的代碼設置secure屬性為true:

 

Cookie cookie = new Cookie("time", "20080808"); // 新建Cookie

cookie.setSecure(true);                           // 設置安全屬性

response.addCookie(cookie);                        // 輸出到客戶端

 

提示:secure屬性并不能對Cookie內(nèi)容加密,因而不能保證絕對的安全性。如果需要高安全性,需要在程序中對Cookie內(nèi)容加密、解密,以防泄密。

 

1.1.12  JavaScript操作Cookie

Cookie是保存在瀏覽器端的,因此瀏覽器具有操作Cookie的先決條件。瀏覽器可以使用腳本程序如JavaScript或者VBScript等操作Cookie。這里以JavaScript為例介紹常用的Cookie操作。例如下面的代碼會輸出本頁面所有的Cookie。

<script>document.write(document.cookie);</script>

由于JavaScript能夠任意地讀寫Cookie,有些好事者便想使用JavaScript程序去窺探用戶在其他網(wǎng)站的Cookie。不過這是徒勞的,W3C組織早就意識到JavaScript對Cookie的讀寫所帶來的安全隱患并加以防備了,W3C標準的瀏覽器會阻止JavaScript讀寫任何不屬于自己網(wǎng)站的Cookie。換句話說,A網(wǎng)站的JavaScript程序讀寫B(tài)網(wǎng)站的Cookie不會有任何結(jié)果。

 

1.1.13  案例:永久登錄

如果用戶是在自己家的電腦上上網(wǎng),登錄時就可以記住他的登錄信息,下次訪問時不需要再次登錄,直接訪問即可。實現(xiàn)方法是把登錄信息如賬號、密碼等保存在Cookie中,并控制Cookie的有效期,下次訪問時再驗證Cookie中的登錄信息即可。

保存登錄信息有多種方案。最直接的是把用戶名與密碼都保持到Cookie中,下次訪問時檢查Cookie中的用戶名與密碼,與數(shù)據(jù)庫比較。這是一種比較危險的選擇,一般不把密碼等重要信息保存到Cookie中。

還有一種方案是把密碼加密后保存到Cookie中,下次訪問時解密并與數(shù)據(jù)庫比較。這種方案略微安全一些。如果不希望保存密碼,還可以把登錄的時間戳保存到Cookie與數(shù)據(jù)庫中,到時只驗證用戶名與登錄時間戳就可以了。

這幾種方案驗證賬號時都要查詢數(shù)據(jù)庫。

本例將采用另一種方案,只在登錄時查詢一次數(shù)據(jù)庫,以后訪問驗證登錄信息時不再查詢數(shù)據(jù)庫。實現(xiàn)方式是把賬號按照一定的規(guī)則加密后,連同賬號一塊保存到Cookie中。下次訪問時只需要判斷賬號的加密規(guī)則是否正確即可。本例把賬號保存到名為account的Cookie中,把賬號連同密鑰用MD1算法加密后保存到名為ssid的Cookie中。驗證時驗證Cookie中的賬號與密鑰加密后是否與Cookie中的ssid相等。相關代碼如下:

代碼1.8 loginCookie.jsp

<%@ page language="java"pageEncoding="UTF-8" isErrorPage="false" %>

<%!                                                  // JSP方法

    private static final String KEY =":cookie@helloweenvsfei.com";
                                                     // 密鑰 

    public final static String calcMD1(Stringss) { // MD1 加密算法

       String s = ss==null ?"" : ss;                  // 若為null返回空

       char hexDigits[] = { '0','1', '2', '3', '4', '1', '6', '7', '8', '9',
       'a', 'b', 'c', 'd', 'e', 'f' };                        // 字典

       try {

        byte[] strTemp =s.getBytes();                          // 獲取字節(jié)

        MessageDigestmdTemp = MessageDigest.getInstance("MD1"); // 獲取MD1

       mdTemp.update(strTemp);                                // 更新數(shù)據(jù)

        byte[] md =mdTemp.digest();                        // 加密

        int j =md.length;                                 // 加密后的長度

        char str[] = newchar[j * 2];                       // 新字符串數(shù)組

        int k =0;                                         // 計數(shù)器k

        for (int i = 0; i< j; i++) {                       // 循環(huán)輸出

         byte byte0 =md[i];

         str[k++] =hexDigits[byte0 >>> 4 & 0xf];

         str[k++] =hexDigits[byte0 & 0xf];

        }

        return newString(str);                             // 加密后字符串

       } catch (Exception e){return null; }

    }

%>

<%

   request.setCharacterEncoding("UTF-8");             // 設置request編碼

    response.setCharacterEncoding("UTF-8");        // 設置response編碼

   

    String action =request.getParameter("action"); // 獲取action參數(shù)

   

    if("login".equals(action)){                       // 如果為login動作

        String account =request.getParameter("account");
                                                     // 獲取account參數(shù)

        String password =request.getParameter("password");


                    &

分享題目:Cookie與Session有何異同?
URL標題:http://muchs.cn/news3/105103.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供域名注冊網(wǎng)站策劃、做網(wǎng)站、網(wǎng)站排名、移動網(wǎng)站建設、網(wǎng)站設計公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

搜索引擎優(yōu)化