天天看點

Cookie和Session專題

一、cookie機制和session機制的差別

*************************************************************************************

具體來說cookie機制采用的是在用戶端保持狀态的方案,而session機制采用的是在伺服器端保持狀态的方案。

同時我們也看到,由于才伺服器端保持狀态的方案在用戶端也需要儲存一個辨別,是以session

機制可能需要借助于cookie機制來達到儲存辨別的目的,但實際上還有其他選擇

二、會話cookie和持久cookie的差別

如果不設定過期時間,則表示這個cookie生命周期為浏覽器會話期間,隻要關閉浏覽器視窗,cookie就消失了。這種生命期為浏覽會話期的cookie被稱為會話cookie。會話cookie一般不儲存在硬碟上而是儲存在記憶體裡。

  如果設定了過期時間,浏覽器就會把cookie儲存到硬碟上,關閉後再次打開浏覽器,這些cookie依然有效直到超過設定的過期時間。

  存儲在硬碟上的cookie可以在不同的浏覽器程序間共享,比如兩個IE視窗。而對于儲存在記憶體的cookie,不同的浏覽器有不同的處理方式。

三、如何利用實作自動登入

  當使用者在某個網站注冊後,就會收到一個惟一使用者ID的cookie。客戶後來重新連接配接時,這個

使用者ID會自動傳回,伺服器對它進行檢查,确定它是否為注冊使用者且選擇了自動登入,進而使使用者務需給出明确的使用者名和密碼,就可以通路伺服器上的資源。

四、如何根據使用者的愛好定制站點

  網站可以使用cookie記錄使用者的意願。對于簡單的設定,網站可以直接将頁面的設定存儲在cookie中完成定制。然而對于更複雜的定制,網站隻需僅将一個惟一的辨別符發送給使用者,由伺服器端的資料庫存儲每個辨別符對應的頁面設定。

五、cookie的發送

1.建立Cookie對象

2.設定最大時效

3.将Cookie放入到HTTP響應報頭

如果你建立了一個cookie,并将他發送到浏覽器,預設情況下它是一個會話級别的cookie:存儲在浏覽器的記憶體中,使用者退出浏覽器之後被删除。如果你希望浏覽器将該cookie存儲在磁盤上,則

需要使用maxAge,并給出一個以秒為機關的時間。将最大時效設為0則是指令浏覽器删除該cookie。

送cookie需要使用HttpServletResponse的addCookie方法,将cookie插入到一個Set-Cookie HTTP請求

報頭中。由于這個方法并不修改任何之前指定的Set-Cookie報頭,而是建立新的報頭,是以我們将這個方法稱為是addCookie,而非

setCookie。同樣要記住響應報頭必須在任何文檔内容發送到用戶端之前設定。

六、cookie的讀取

1.調用request.getCookie

要擷取有浏覽器發送來的cookie,需要調用HttpServletRequest的getCookies方法,這個調用傳回Cookie對象的數組,對應由HTTP請求中Cookie報頭輸入的值。

2.對數組進行循環,調用每個cookie的getName方法,直到找到感興趣的cookie為止

 cookie與你的主機(域)相關,而非你的servlet或JSP頁面。因而,盡管你的servlet可能隻發送了單個cookie,你也可能會得到許多不相關的cookie。

例如:

  String cookieName = “userID”;

    Cookie cookies[] = request.getCookies();

    if (cookies!=null){

        for(int i=0;i<cookies.length;i++){

    Cookie cookie = cookies[i];

    if (cookieName.equals(cookie.getName())){

        doSomethingWith(cookie.getValue());

}

七、如何使用cookie檢測初訪者

A.調用HttpServletRequest.getCookies()擷取Cookie數組

B.在循環中檢索指定名字的cookie是否存在以及對應的值是否正确

C.如果是則退出循環并設定差別辨別

D.根據差別辨別判斷使用者是否為初訪者進而進行不同的操作

八、使用cookie檢測初訪者的常見錯誤

不能僅僅因為cookie數組中不存在在特定的資料項就認為使用者是個初訪者。如果cookie數組為null,客戶可能是一個初訪者,也可能是由于使用者将cookie删除或禁用造成的結果。

但是,如果數組非null,也不過是顯示客戶曾經到過你的網站或域,并不能說明他們曾經通路過你的servlet。其它servlet、JSP頁面以及非Java Web應用都可以設定cookie,依據路徑的設定,其中的任何cookie都有可能傳回給使用者的浏覽器。

正确的做法是判斷cookie數組是否為空且是否存在指定的Cookie對象且值正确。

九、使用cookie屬性的注意問題

  屬性是從伺服器發送到浏覽器的報頭的一部分;但它們不屬于由浏覽器傳回給伺服器的報頭。 

  是以除了名稱和值之外,cookie屬性隻适用于從伺服器輸出到用戶端的cookie;伺服器端來自于浏覽器的cookie并沒有設定這些屬性。 

 

 因而不要期望通過request.getCookies得到的cookie中可以使用這個屬性。這意味着,你不能僅僅通過設定cookie的最大時效,

發出它,在随後的輸入數組中查找适當的cookie,讀取它的值,修改它并将它存回Cookie,進而實作不斷改變的cookie值。

十、如何使用cookie記錄各個使用者的通路計數

1.擷取cookie數組中專門用于統計使用者通路次數的cookie的值

2.将值轉換成int型

3.将值加1并用原來的名稱重新建立一個Cookie對象

4.重新設定最大時效

5.将新的cookie輸出

十一、session在不同環境下的不同含義

session,中文經常翻譯為會話,其本來的含義是指有始有終的一系列動作/消息,比如打電話是從拿起電話撥号到挂斷電話這中間的一系列過程可以稱之為一個session。

然而當session一詞與網絡協定相關聯時,它又往往隐含了“面向連接配接”和/或“保持狀态”這樣兩個含義。

  session在Web開發環境下的語義又有了新的擴充,它的含義是指一類用來在用戶端與伺服器端之間保持狀态的解決方案。有時候Session也用來指這種解決方案的存儲結構。

十二、session的機制

  session機制是一種伺服器端的機制,伺服器使用一種類似于散清單的結構(也可能就是使用散清單)來儲存資訊。

程式需要為某個用戶端的請求建立一個session的時候,伺服器首先檢查這個用戶端的請求裡是否包含了一個session辨別-稱為

session id,如果已經包含一個session id則說明以前已經為此客戶建立過session,伺服器就按照session id把這個

session檢索出來使用(如果檢索不到,可能會建立一個,這種情況可能出現在服務端已經删除了該使用者對應的session對象,但使用者人為地在請求的

URL後面附加上一個JSESSION的參數)。

如果客戶請求不包含session id,則為此客戶建立一個session并且生成一個與此session相關聯的session id,這個session id将在本次響應中傳回給用戶端儲存。

十三、儲存session id的幾種方式

A.儲存session id的方式可以采用cookie,這樣在互動過程中浏覽器可以自動的按照規則把這個辨別發送給伺服器。

B.

由于cookie可以被人為的禁止,必須有其它的機制以便在cookie被禁止時仍然能夠把session id傳遞回伺服器,經常采用的一種技術叫做

URL重寫,就是把session id附加在URL路徑的後面,附加的方式也有兩種,一種是作為URL路徑的附加資訊,另一種是作為查詢字元串附加在

URL後面。網絡在整個互動過程中始終保持狀态,就必須在每個用戶端可能請求的路徑後面都包含這個session id。

C.另一種技術叫做表單隐藏字段。就是伺服器會自動修改表單,添加一個隐藏字段,以便在表單送出時能夠把session id傳遞回伺服器。

十四、session什麼時候被建立

一個常見的錯誤是以為session在有用戶端通路時就被建立,然而事實是直到某server端程式(如Servlet)調用HttpServletRequest.getSession(true)這樣的語句時才會被建立。

十五、session何時被删除

session在下列情況下被删除:

A.程式調用HttpSession.invalidate()

B.距離上一次收到用戶端發送的session id時間間隔超過了session的最大有效時間

C.伺服器程序被停止

再次注意關閉浏覽器隻會使存儲在用戶端浏覽器記憶體中的session cookie失效,不會使伺服器端的session對象失效。

十六、URL重寫有什麼缺點

   對所有的URL使用URL重寫,包括超連結,form的action,和重定向的URL。每個引用你的站點的URL,以及那些傳回給使用者的URL(即使通過間接手段,比如伺服器重定向中的Location字段)都要添加額外的資訊。

  這意味着在你的站點上不能有任何靜态的HTML頁面(至少靜态頁面中不能有任何連結到站點動态頁面的連結)。是以,每個頁面都必須使用servlet

或JSP動态生成。即使所有的頁面都動态生成,如果使用者離開了會話并通過書簽或連結再次回來,會話的資訊都會丢失,因為存儲下來的連結含有錯誤的辨別資訊

-該URL後面的SESSION ID已經過期了。  

十七、使用隐藏的表單域有什麼缺點

    僅當每個頁面都是有表單送出而動态生成時,才能使用這種方法。單擊正常的<A HREF..>超文本連結并不産生表單送出,是以隐藏的表單域不能支援通常的會話跟蹤,隻能用于一系列特定的操作中,比如線上商店的結賬過程

十八、會話跟蹤的基本步驟

1.通路與目前請求相關的會話對象

2.查找與會話相關的資訊

3.存儲會話資訊

4.廢棄會話資料

十九、getSession()/getSession(true)、getSession(false)的差別

getSession()/getSession(true):當session存在時傳回該session,否則建立一個session并傳回該對象

getSession(false):當session存在時傳回該session,否則不會建立session,傳回null

二十、如何将資訊于會話關聯起來

  setAttribute會替換任何之前設定的值;如果想要在不提供任何代替的情況下移除某個值,則應使用removeAttribute。這個方法會觸發所有實作了HttpSessionBindingListener接口的值的valueUnbound

方法。

二十一、會話屬性的類型有什麼限制嗎

通常會話屬性的類型隻要是Object就可以了。除了null或基本類型,如int,double,boolean。

如果要使用基本類型的值作為屬性,必須将其轉換為相應的封裝類對象

二十二、如何廢棄會話資料

A.隻移除自己編寫的servlet建立的資料:

   調用removeAttribute(“key”)将指定鍵關聯的值廢棄

B.删除整個會話(在目前Web應用中):

   調用invalidate,将整個會話廢棄掉。這樣做會丢失該使用者的所有會話資料,而非僅僅由我們

servlet或JSP頁面建立的會話資料

C.将使用者從系統中登出并删除所有屬于他(或她)的會話

   調用logOut,将客戶從Web伺服器中登出,同時廢棄所有與該使用者相關聯的會話(每個Web應用至多一個)。這個操作有可能影響到伺服器上多個不同的Web應用

二十三、使用isNew來判斷使用者是否為新舊使用者的錯誤做法

public boolean isNew()方法如果會話尚未和客戶程式(浏覽器)發生任何聯系,則這個方法傳回true,這一般是因為會話是建立的,不是由輸入的客戶請求所引起的。

但如果isNew傳回false,隻不過是說明他之前曾經通路該Web應用,并不代表他們曾通路過我們的servlet或JSP頁面。

因為session是與使用者相關的,在使用者之前通路的每一個頁面都有可能建立了會話。是以isNew為false隻能說使用者之前通路過該Web應用,session可以是目前頁面建立,也可能是由使用者之前通路過的頁面建立的。

正确的做法是判斷某個session中是否存在某個特定的key且其value是否正确

二十四、Cookie的過期和Session的逾時有什麼差別

會話的逾時由伺服器來維護,它不同于Cookie的失效日期。首先,會話一般基于駐留記憶體的cookie

不是持續性的cookie,因而也就沒有截至日期。即使截取到JSESSIONID cookie,并為它設定一個失效日期發送出去。浏覽器會話和伺服器會話也會截然不同。

二十五、session cookie和session對象的生命周期是一樣的嗎

當使用者關閉了浏覽器雖然session cookie已經消失,但session對象仍然儲存在伺服器端

二十六、是否隻要關閉浏覽器,session就消失了

程式一般都是在使用者做log off的時候發個指令去删除session,然而浏覽器從來不會主動在關閉之前通知伺服器它将要被關閉,是以伺服器根本不會有機會知道浏覽器已經關閉。伺服器會一直保留這個會話對象直到它處于非活動狀态超過設定的間隔為止。

之是以會有這種錯誤的認識,是因為大部分session機制都使用會話cookie來儲存session id,而關閉浏覽器後這個session id就消失了,再次連接配接到伺服器時也就無法找到原來的session。

如果伺服器設定的cookie被儲存到硬碟上,或者使用某種手段改寫浏覽器發出的HTTP請求報頭,把原來的session id發送到伺服器,則再次打開浏覽器仍然能夠找到原來的session。

恰恰是由于關閉浏覽器不會導緻session被删除,迫使伺服器為session設定了一個失效時間,當距離客戶上一次使用session的時間超過了這個失效時間時,伺服器就可以認為用戶端已經停止了活動,才會把session删除以節省存儲空間。

  由此我們可以得出如下結論:

  關閉浏覽器,隻會是浏覽器端記憶體裡的session cookie消失,但不會使儲存在伺服器端的session對象消失,同樣也不會使已經儲存到硬碟上的持久化cookie消失。

二十七、打開兩個浏覽器視窗通路應用程式會使用同一個session還是不同的session

通常session cookie是不能跨視窗使用的,當你新開了一個浏覽器視窗進入相同頁面時,系統會賦予你一個新的session id,這樣我們資訊共享的目的就達不到了。

時我們可以先把session id儲存在persistent cookie中(通過設定session的最大有效時間),然後在新視窗中讀出來,就可

以得到上一個視窗的session id了,這樣通過session cookie和persistent cookie的結合我們就可以實作了跨視窗的

會話跟蹤。

二十八、如何使用會話顯示每個客戶的通路次數

由于客戶的通路次數是一個整型的變量,但session的屬性類型中不能使用int,double,boolean等基本類型的變量,是以我們要用到這些基本類型的封裝類型對象作為session對象中屬性的值

  但像Integer是一種不可修改(Immutable)的資料結構:建構後就不能更改。這意味着每個請求都必須建立新的Integer對象,之後使用setAttribute來代替之前存在的老的屬性的值。例如:

HttpSession session = request.getSession();

SomeImmutalbeClass value = (SomeImmutableClass)session.getAttribute(“SomeIdentifier”);

if (value= =null){

    value = new SomeImmutableClass(…); // 新建立一個不可更改對象

}else{

    value = new SomeImmutableClass(calculatedFrom(value)); // 對value重新計算後建立新的對象

session.setAttribute(“someIdentifier”,value); // 使用新建立的對象覆寫原來的老的對象

二十九、如何使用會話累計使用者的資料

使用可變的資料結構,比如數組、List、Map或含有可寫字段的應用程式專有的資料結構。通過這種方式,除非首次配置設定對象,否則不需要調用setAttribute。例如

SomeMutableClass value = (SomeMutableClass)session.getAttribute(“someIdentifier”);

if(value = = null){

    value = new SomeMutableClass(…);

    session.setAttribute(“someIdentifier”,value);

    value.updateInternalAttribute(…);     // 如果已經存在該對象則更新其屬性而不需重新設定屬性

三十、不可更改對象和可更改對象在會話資料更新時的不同處理

不可更改對象因為一旦建立之後就不能更改,是以每次要修改會話中屬性的值的時候,都需要

調用setAttribute(“someIdentifier”,newValue)來代替原有的屬性的值,否則屬性的值不會被更新

可更改對象因為其自身一般提供了修改自身屬性的方法,是以每次要修改會話中屬性的值的時

候,隻要調用該可更改對象的相關修改自身屬性的方法就可以了。這意味着我們就不需要調

用setAttribute方法了