Session,Cookie,jsessionid,Url重寫

cactusz發表於2017-07-06

在一些投票之類的場合,我們往往因為公平的原則要求每人只能投一票,在一些WEB開發中也有類似的情況,這時候我們通常會使用COOKIE來實現,例如如下的程式碼:

< % cookie[]cookies = request.getCookies();

if (cookies.lenght == 0 || cookies == null){

doStuffForNewbie();

//沒有訪問過

}else{

doStuffForReturnVisitor(); //已經訪問過了

}

% >

 

這是很淺顯易懂的道理,檢測COOKIE的存在,如果存在說明已經執行過寫入COOKIE的程式碼了,然而執行以上的程式碼後,無論何時結果都是執行doStuffForReturnVisitor(),通過控制皮膚-Internet選項-設定-察看檔案卻始終看不到生成的cookie檔案,奇怪,程式碼明明沒有問題,不過既然有cookie,那就顯示出來看看。

cookie[]cookies = request.getCookies();

if (cookies.lenght == 0 || cookies == null)

out.println("Has not visited this website");

}else{

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

out.println("cookie name:" + cookies[i].getName() + "cookie value:" +

cookie[i].getValue());

}

}

 

執行結果:

cookie name:JSESSIONID cookie value:KWJHUG6JJM65HS2K6

 

為什麼會有cookie呢,大家都知道,http是無狀態的協議,客戶每次讀取web頁面時,伺服器都開啟新的會話,而且伺服器也不會自動維護客戶的上下文資訊,那麼要怎麼才能實現網上商店中的購物車呢,session就是一種儲存上下文資訊的機制,它是針對每一個使用者的,變數的值儲存在伺服器端,通過SessionID來區分不同的客戶,session是以cookie或URL重寫為基礎的,預設使用cookie來實現,系統會創造一個名為JSESSIONID的輸出cookie,我們叫做session cookie,以區別persistent cookies,也就是我們通常所說的cookie,注意session cookie是儲存於瀏覽器記憶體中的,並不是寫到硬碟上的,這也就是我們剛才看到的JSESSIONID,我們通常情是看不到JSESSIONID的,但是當我們把瀏覽器的cookie禁止後,web伺服器會採用URL重寫的方式傳遞Sessionid,我們就可以在位址列看到sessionid=KWJHUG6JJM65HS2K6之類的字串。

 

明白了原理,我們就可以很容易的分辨出persistent cookies和session cookie的區別了,網上那些關於兩者安全性的討論也就一目瞭然了,session cookie針對某一次會話而言,會話結束session cookie也就隨著消失了,而persistent cookie只是存在於客戶端硬碟上的一段文字(通常是加密的),而且可能會遭到cookie欺騙以及針對cookie的跨站指令碼攻擊,自然不如session cookie安全了。

 

通常session cookie是不能跨視窗使用的,當你新開了一個瀏覽器視窗進入相同頁面時,系統會賦予你一個新的sessionid,這樣我們資訊共享的目的就達不到了,此時我們可以先把sessionid儲存在persistent cookie中,然後在新視窗中讀出來,就可以得到上一個視窗SessionID了,這樣通過session cookie和persistent cookie的結合我們就實現了跨視窗的session tracking(會話跟蹤)。

 

      在一些web開發的書中,往往只是簡單的把Session和cookie作為兩種並列的http傳送資訊的方式,session cookies位於伺服器端,persistent cookie位於客戶端,可是session又是以cookie為基礎的,明白的兩者之間的聯絡和區別,我們就不難選擇合適的技術來開發web service了。

 

 

cookie和session機制之間的區別與聯絡

       具體來說cookie機制採用的是在客戶端保持狀態的方案。它是在使用者端的會話狀態的存貯機制,他需要使用者開啟客戶端的cookie支援。cookie的作用就是為了解決HTTP協議無狀態的缺陷所作的努力.

 

       而session機制採用的是一種在客戶端與伺服器之間保持狀態的解決方案。同時我們也看到,由於採用伺服器端保持狀態的方案在客戶端也需要儲存一個標識,所以session機制可能需要藉助於cookie機制來達到儲存標識的目的。而session提供了方便管理全域性變數的方式

 

  session是針對每一個使用者的,變數的值儲存在伺服器上,用一個sessionID來區分是哪個使用者session變數,這個值是通過使用者的瀏覽器在訪問的時候返回給伺服器,當客戶禁用cookie時,這個值也可能設定為由get來返回給伺服器。

 

  就安全性來說:當你訪問一個使用session 的站點,同時在自己機子上建立一個cookie,建議在伺服器端的SESSION機制更安全些.因為它不會任意讀取客戶儲存的資訊。

 

  正統的cookie分發是通過擴充套件HTTP協議來實現的,伺服器通過在HTTP的響應頭中加上一行特殊的指示以提示瀏覽器按照指示生成相應的cookie。然而純粹的客戶端指令碼如JavaScript或者VBScript也可以生成cookie。而cookie的使用是由瀏覽器按照一定的原則在後臺自動傳送給伺服器的。瀏覽器檢查所有儲存的cookie,如果某個cookie所宣告的作用範圍大於等於將要請求的資源所在的位置,則把該cookie附在請求資源的HTTP請求頭上傳送給伺服器。

 

  從網路伺服器觀點看所有HTTP請求都獨立於先前請求。就是說每一個HTTP響應完全依賴於相應請求中包含的資訊狀態管理機制克服了HTTP的一些限制並允許網路客戶端及伺服器端維護請求間的關係。在這種關係維持的期間叫做會話(session)。

 

  Cookies是伺服器在本地機器上儲存的小段文字並隨每一個請求傳送至同一個伺服器。IETF RFC 2965 HTTP State Management Mechanism 是通用cookie規範。網路伺服器用HTTP頭向客戶端傳送cookies,在客戶終端,瀏覽器解析這些cookies並將它們儲存為一個本地檔案,它會自動將同一伺服器的任何請求縛上這些cookies。

 

       cookie的內容主要包括:名字,值,過期時間,路徑和域。路徑與域一起構成cookie的作用範圍。若不設定過期時間,則表示這個cookie的生命期為瀏覽器會話期間,關閉瀏覽器視窗,cookie就消失。這種生命期為瀏覽器會話期的cookie被稱為會話cookie。會話cookie一般不儲存在硬碟上而是儲存在記憶體裡,當然這種行為並不是規範規定的。若設定了過期時間,瀏覽器就會把cookie儲存到硬碟上,關閉後再次開啟瀏覽器,這些cookie仍然有效直到超過設定的過期時間。儲存在硬碟上的cookie可以在不同的瀏覽器程式間共享,比如兩個IE視窗。而對於儲存在記憶體裡的cookie,不同的瀏覽器有不同的處理方式。

 

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

 

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

 

儲存這個session id的方式可以採用cookie,這樣在互動過程中瀏覽器可以自動的按照規則把這個標識發揮給伺服器。一般這個cookie的名字都是類似於SEEESIONID。但cookie可以被人為的禁止,則必須有其他機制以便在cookie被禁止時仍然能夠把session id傳遞迴伺服器。

 

經常被使用的一種技術叫做URL重寫,就是把session id直接附加在URL路徑的後面。還有一種技術叫做表單隱藏欄位。就是伺服器會自動修改表單,新增一個隱藏欄位,以便在表單提交時能夠把session id傳遞迴伺服器。比如:

 

<form name="testform" action="/xxx">

<input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">

<input type="text">

</form>

 

什麼是Url重寫?

 

伺服器也可以通過URL重寫的方式來傳遞SessionID的值,因此不是完全依賴Cookie。如果客戶端Cookie禁用,則伺服器可以自動通過重寫URL的方式來儲存Session的值,並且這個過程對程式設計師透明。

 

可以試一下,即使不寫Cookie,在使用request.getCookies();取出的Cookie陣列的長度也是1,而這個Cookie的名字就是JSESSIONID,還有一個很長的二進位制的字串,是SessionID的值。

 

實質上 URL 重寫是通過向 URL 連線新增引數,並把 session ID 作為值包含在連線中。然而,為使這生效,你需要為你的 servlet 響應部分的每個連線新增 session ID.

 

利用Url進行Session重寫如何實現?

 

JSP實現

把 session ID 加到一個連線可以使用一對方法來簡化:response.encodeURL() 使 URL包含 session ID,如果你需要使用重定向,可以使用 response.encodeRedirectURL ()來對 URL 進行編碼。encodeURL () 及 encodeRedirectedURL () 方法首先判斷 cookie是否被瀏覽器支援;如果支援,則引數 URL 被原樣返回,session ID 將通過 cookies 來維持。

程式碼示例:

不使用Url重寫:<a href=http://wwww.myserver.com/servelet/user;userName=awaysrain>Link</a>

使用Url重寫:通過HttpServletResponse介面中的encodeURL()方法編碼.

String myURL = response.encodeURL(http://wwww.myserver.com/servelet/user);

<a href= <%=myURL%> _fcksavedurl=" <%=myURL%>" _fcksavedurl=" <%=myURL%>" _fcksavedurl=" <%=myURL%>" >

 

JSTL實現

<c:url>可以為會話管理重寫 URL

<a href="<c:url value='/content/sitemap.jsp'/>">View sitemap</a>

 

 

Struts實現:

struts配置檔案中:設定屬性redirect, contextRelative

 

<forward name="listArticlesForBlog"

path="/template/listArticlesForBlog.jsp"

redirect="true"

contextRelative="true"/>

 

最後一個比較搞的問題:

那麼在瀏覽器允許cookie的情況下,不要求瀏覽器關閉cookie的情況下使用

url重寫如何實現?

http://tomcat.apache.org/tomcat-5.5-doc/config/context.html

Context支援cookies引數。 設定cookies="false",強制只從url解析sessionid。

 

cookies

Set to true if you want cookies to be used for session identifierContext

communication if supported by the client (this is the default). Set to

false if you want to disable the use of cookies for session identifier

communication, and rely only on URL rewriting by the application.

 

相關文章