1. 程式人生 > >session和cookie理解

session和cookie理解

問題引入

需要說明的是,我們在使用Java(包含但不僅限)進行web開發的過程中,一般採用http作為前後端互動的協議,那麼這裡需要明白一下HTTP是無狀態的。簡單來講,使用HTTP協議訪問伺服器的 時候,每次訪問是沒有相互影響的,這就可以是無狀態的。 但是存在一個問題,伺服器需要儲存使用者訪問的一些狀態。大家想一下,為什麼每次你登陸淘寶和京東的過程中會有一些物品推薦,那麼這些資料是如何出來的(所謂的各種推薦演算法),還有為什麼知道是我是我呢?原因就在與伺服器儲存了你的登陸資訊,所以當你在此訪問伺服器的時候我就知道你是你了。

Http協議是無狀態的,也就導致伺服器無法分辨是誰瀏覽了網頁。為維持使用者在網站的狀態,比如登陸、購物車

等,出現了先後出現了四種技術,分別是隱藏表單域、URL重寫、cookie、session

session和cookie簡單說明

本質上這兩個技術(概念),其目的就是為了在儲存使用者資訊。 session:解決Http協議不能維持狀態的問題,但是session只儲存在伺服器端的,不會在網路中進行傳輸。[服務端狀態儲存技術] cookie:是瀏覽器儲存在使用者電腦上的一小段文字,用來儲存使用者在網站上的必要的資訊。[客戶端狀態儲存技術]。

通過登陸瞭解cookie和session

1.使用者在登入時向後端伺服器傳送HTTP請求,攜帶username和password; 2.伺服器接受請求,執行登陸邏輯,生成使用者session儲存使用者登陸資訊,同時伺服器端生成對應的cookie

,該cookie中包含了sessionID,響應給瀏覽器; 2.瀏覽器本地儲存cookie值; 3.登入後,使用者再向伺服器傳送請求到伺服器,則帶著瀏覽器本地儲存的cookie值; 4.伺服器在接受到請求後,獲取到請求引數(裡面帶有cookie),伺服器從cookie值取出sessionID,根據sessionID找到對應session,若有對應的session則可以執行相應的操作,否者需要進行其他處理。 大家可以看一幅如下圖理解一下: 在這裡插入圖片描述

session和cookie有啥區別?

  • cookie和session都是基於鍵值對的字串,都由後端伺服器生成
  • cookie字串儲存在客戶端瀏覽器中,session值儲存在伺服器中,session比cookie更安全。
  • session是key-value格式的資料,則它的鍵session_id儲存在cookie中的,值session_data儲存在伺服器,通過key來取到value;

cookie機制

S(服務端)—>C(客戶端) 生成cookie

正統的cookie分發是通過擴充套件HTTP協議來實現的,伺服器通過在HTTP的響應頭中加上一行特殊的指示以提示瀏覽器按照指示生成相應的cookie。

C(客戶端) —>S(服務端)傳遞cookie

而cookie 的使用是由瀏覽器按照一定的原則在後臺自動傳送給伺服器的。瀏覽器檢查所有儲存的cookie,如果某個cookie所宣告的作用範圍大於等於將要請求的資源所在的位置,則把該cookie附在請求資源的HTTP請求頭上傳送給伺服器。

cookie的內容主要包括:名字,值,過期時間,路徑和域。

域(域名)

路徑

就是跟在域名後面的URL路徑,例如:/或者/foo等等,路徑與域合在一起就構成了cookie的作用範圍。

過期時間

如果不設定過期時間,則表示這個cookie的生命期為瀏覽器會話期間,只要關閉瀏覽器視窗,cookie就消失了。這種生命期為瀏覽器會話期的 cookie被稱為會話cookie。會話cookie一般不儲存在硬碟上而是儲存在記憶體裡,當然這種行為並不是規範規定的。 如果設定了過期時間,瀏覽器就會把cookie儲存到硬碟上,關閉後再次開啟瀏覽器,這些cookie仍然有效直到超過設定的過期時間。 下面就是一個goolge設定cookie的響應頭的例子 HTTP/1.1 302 Found Location: http://www.google.com/intl/zh-CN/ Set-Cookie: PREF=ID=0565f77e132de138:NW=1:TM=1098082649:LM=1098082649:S=KaeaCFPo49RiA_d8; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com Content-Type: text/html 瀏覽器在再次訪問goolge的資源時自動向外發送cookie

session機制

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

session建立

當程式需要為某個客戶端的請求建立一個session的時候,伺服器首先檢查這個客戶端的請求裡是否已包含了一個session標識 - 稱為session id,如果已包含一個session id則說明以前已經為此客戶端建立過session,伺服器就按照session id把這個 session檢索出來使用(如果檢索不到,可能會新建一個),如果客戶端請求不包含session id,則為此客戶端建立一個session並且生成一個與此session相關聯的session id,session id的值應該是一個既不會重複,又不容易被找到規律以仿造的字串,這個 session id將被在本次響應中返回給客戶端儲存。

sessionID 儲存

cookie

儲存這個session id的方式可以採用cookie,這樣在互動過程中瀏覽器可以自動的按照規則把這個標識返回給伺服器。一般這個cookie的名字都是類似於SEEESIONID,而。比如weblogic對於web應用程式生成的cookie,JSESSIONID= yOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764,它的名字就是 JSESSIONID。

URL重寫

由於cookie可以被人為的禁止,必須有其他機制以便在cookie被禁止時仍然能夠把session id傳遞迴伺服器。經常被使用的一種技術叫做URL重寫,就是把session id直接附加在URL路徑的後面,附加方式也有兩種:

  1. 一種是作為URL路徑的附加資訊,表現形式為http://…/xxx;jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
  2. 另一種是作為查詢字串附加在URL後面,表現形式為http://…/xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764

這兩種方式對於使用者來說是沒有區別的,只是伺服器在解析的時候處理的方式不同,採用第一種方式也有利於把session id的資訊和正常程式引數區分開來。為了在整個互動過程中始終保持狀態,就必須在每個客戶端可能請求的路徑後面都包含這個session id。

表單隱藏欄位

就是伺服器會自動修改表單,新增一個隱藏欄位,以便在表單提交時能夠把session id傳遞迴伺服器。比如下面的表單

<form name="testform" action="/xxx">
<input type="text">
</form>
在被傳遞給客戶端之前將被改寫成
<form name="testform" action="/xxx">
<input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">
<input type="text">
</form>

在談論session機制的時候,常常聽到這樣一種誤解“只要關閉瀏覽器,session就消失了”。其實可以想象一下會員卡,除非顧客主動對店家提出銷卡,否則店家絕對不會輕易刪除顧客的資料。對session來說也是一樣的,除非程式通知伺服器刪除一個session,否則伺服器會一直保留,程式一般都是在使用者做log off的時候發個指令去刪除session。然而瀏覽器從來不會主動在關閉之前通知伺服器它將要關閉,因此伺服器根本不會有機會知道瀏覽器已經關閉,之所以會有這種錯覺,是大部分session機制都使用會話cookie來儲存session id,而關閉瀏覽器後這個 session id就消失了,再次連線伺服器時也就無法找到原來的session。如果伺服器設定的cookie被儲存到硬碟上,或者使用某種手段改寫瀏覽器發出的HTTP請求頭,把原來的session id傳送給伺服器,則再次開啟瀏覽器仍然能夠找到原來的session。 恰恰是由於關閉瀏覽器不會導致session被刪除,迫使伺服器為seesion設定了一個失效時間,當距離客戶端上一次使用session的時間超過這個失效時間時,伺服器就可以認為客戶端已經停止了活動,才會把session刪除以節省儲存空間。

常見的問題

session問題

1、session在何時被建立

一個常見的誤解是以為session在有客戶端訪問時就被建立,然而事實是直到某server端程式呼叫HttpServletRequest.getSession(true)這樣的語句時才被建立,注意如果JSP沒有顯示的使用 <% @page session=“false”%>關閉session,則JSP檔案在編譯成Servlet時將會自動加上這樣一條語句HttpSession session = HttpServletRequest.getSession(true);這也是JSP中隱含的 session物件的來歷。由於session會消耗記憶體資源,因此,如果不打算使用session,應該在所有的JSP中關閉它。

2、session何時被刪除

綜合前面的討論,session在下列情況下被刪除 a.程式呼叫HttpSession.invalidate(); b.距離上一次收到客戶端傳送的session id時間間隔超過了session的超時設定; c.伺服器程序被停止(非持久session)

3、如何做到在瀏覽器關閉時刪除session

嚴格的講,做不到這一點。可以做一點努力的辦法是在所有的客戶端頁面裡使用javascript程式碼window.oncolose()來監視瀏覽器的關閉動作,然後向伺服器傳送一個請求來刪除session。但是對於瀏覽器崩潰或者強行殺死程序這些非常規手段仍然無能為力。

4、有個HttpSessionListener是怎麼回事

你可以建立這樣的listener去監控session的建立和銷燬事件,使得在發生這樣的事件時你可以做一些相應的工作。注意是session的建立和銷燬動作觸發listener,而不是相反。類似的與HttpSession有關的listener還有HttpSessionBindingListener,HttpSessionActivationListener和 HttpSessionAttributeListener。

5、存放在session中的物件必須是可序列化的嗎

不是必需的。要求物件可序列化只是為了session能夠在叢集中被複制或者能夠持久儲存或者在必要時server能夠暫時把session交換出記憶體。

6、如何才能正確的應付客戶端禁止cookie的可能性

7、開兩個瀏覽器視窗訪問應用程式會使用同一個session還是不同的session

對session來說是隻認id不認人,因此不同的瀏覽器,不同的視窗開啟方式以及不同的cookie儲存方式都會對這個問題的答案有影響。

8、如何防止使用者開啟兩個瀏覽器視窗操作導致的session混亂

這個問題與防止表單多次提交是類似的,可以通過設定客戶端的令牌來解決。就是在伺服器每次生成一個不同的id返回給客戶端,同時儲存在session裡,客戶端提交表單時必須把這個id也返回伺服器,程式首先比較返回的id與儲存在session裡的值是否一致,如果不一致則說明本次操作已經被提交過了。可以參看《J2EE核心模式》關於表示層模式的部分。需要注意的是對於使用javascript window.open開啟的視窗,一般不設定這個id,或者使用單獨的id,以防主視窗無法操作,建議不要再window.open開啟的窗口裡做修改操作,這樣就可以不用設定。

cookie問題

1、java中cookie設定

2、cookie如何建立

Web 伺服器通過傳送一個稱為 Set-Cookie 的 HTTP 訊息頭來建立一個 cookie,Set-Cookie訊息頭是一個字串,其格式如下(中括號中的部分是可選的): Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure] value部分,通常是一個 name=value 格式的字串。事實上,這種格式是原始規範中指定的格式,但是瀏覽器並不會對 cookie 值按照此格式來驗證。實際上,你可以指定一個不含等號的字串,它同樣會被儲存。然而,最常用的使用方式是按照 name=value 格式來指定 cookie 的值(大多數介面只支援該格式)。 傳送回伺服器的cookie只包含cookie設定的值,而不包含cookie的其他可選項,而且瀏覽器不會對cookie做任何更改,會原封不動的傳送回伺服器。當存在多個cookie時,用分號和空格隔開: Cookie: name=value; name1=value1; name2=value2/pre>