1. 程式人生 > >java基礎學習:JavaWeb之Cookie和Session

java基礎學習:JavaWeb之Cookie和Session

其他更多java基礎文章: java基礎學習(目錄)


一、會話概述

1.1、什麼是會話?

會話可簡單理解為:使用者開一個瀏覽器,點選多個超連結,訪問伺服器多個web資源,然後關閉瀏覽器,整個過程稱之為一個會話其中不管瀏覽器傳送多少請求,都視為一次會話,直到瀏覽器關閉,本次會話結束。
其中注意,一個瀏覽器就相當於一部電話,如果使用火狐瀏覽器,訪問伺服器,就是一次會話了,然後開啟google瀏覽器,訪問伺服器,這是另一個會話,雖然是在同一臺電腦,同一個使用者在訪問,但是,這是兩次不同的會話。

1.2、會話機制

  Web程式中常用的技術,用來跟蹤使用者的整個會話。常用的會話跟蹤技術是Cookie與Session。Cookie通過在客戶端記錄資訊確定使用者身份,Session通過在伺服器端記錄資訊確定使用者身份。

二、Cookie

Cookie是客戶端技術,程式把每個使用者的資料以cookie的形式寫給使用者各自的瀏覽器。當用戶使用瀏覽器再去訪問伺服器中的web資源時,就會帶著各自的資料去。這樣,web資源處理的就是使用者各自的資料了。由於cookie是由客戶端瀏覽器儲存和攜帶的,所以稱之為客戶端技術

2.1、Cookie的工作流程

1)servlet建立cookie,儲存少量資料,傳送瀏覽器。
2)瀏覽器獲得伺服器傳送的cookie資料,將自動的儲存到瀏覽器端。
3)下次訪問時,瀏覽器將自動攜帶cookie資料傳送給伺服器。

2.2、Cookie特點

1)每一個cookie檔案大小:4kb , 如果超過4kb瀏覽器不識別
2)一個web站點(web專案):傳送20個
3)一個瀏覽器儲存總大小:300個
4)cookie 不安全,可能洩露使用者資訊。瀏覽器支援禁用cookie操作。
5) 預設情況生命週期:與瀏覽器會話一樣,當瀏覽器關閉時cookie銷燬的。---臨時cookie

cookie.setMaxAge(expiry);  //設定cookie被瀏覽器儲存的時間。
      
expiry:單位秒,預設為-1,
expiry=-1:代表瀏覽器關閉後,也就是會話結束後,cookie就失效了,也就沒有了。
expiry>0:代表瀏覽器關閉後,cookie不會失效,仍然存在。並且會將cookie儲存到硬碟中,直到設定時間過期才會被瀏覽器自動刪除,
expiry=0:刪除cookie。不管是之前的expiry=-1還是expiry>0,當設定expiry=0時,cookie都會被瀏覽器給刪除。
複製程式碼

2.3、Cookie操作

操作cookie

  1)建立cookie:new Cookie(name,value)
  2)傳送cookie到瀏覽器:HttpServletResponse.addCookie(Cookie)
  3)servlet接收cookie:HttpServletRequest.getCookies() 瀏覽器傳送的所有cookie
複製程式碼

cookie API

    getName() 獲得名稱,cookie中的key
    getValue() 獲得值,cookie中的value
  setValue(java.lang.String newValue)  設定內容,用於修改key對應的value值。
  setMaxAge(int expiry) 設定有效時間【】
  setPath(java.lang.String uri)  設定路徑【】  
  setDomain(java.lang.String pattern) 設定域名 , 一般無效,有瀏覽器自動設定,setDomain(".zyh.com")
    www.zyh.com / bbs.zyh.com 都可以訪問
    a.b.zyh.com無法訪問
    作用:設定cookie的作用範圍,域名+路徑在一起就構成了cookie的作用範圍,上面單獨設定的setPath有用,是因為有瀏覽器自動設定該域名屬性,但是我們必須知道有這麼個屬性進行域名設定的
  isHttpOnly()  是否只是http協議使用。只能servlet的通過getCookies()獲得,javascript不能獲得。
  setComment(java.lang.String purpose) (瞭解)  //對該cookie進行描述的資訊(說明作用),瀏覽器顯示cookie資訊時能看到
  setSecure(boolean flag) (瞭解)  是否使用安全傳輸協議。為true時,只有當是https請求連線時cookie才會傳送給伺服器端,而http時不會,但是服務端還是可以傳送給瀏覽端的。
  setVersion(int v) (瞭解)  引數為0(傳統Netscape cookie規範編譯)或1(RFC 2109規範編譯)。這個沒用到,不是很懂
複製程式碼

注意事項
cookie不能傳送中文,如果要傳送中文,就需要進行特別處理。

Cookie cookie = new Cookie("country", URLEncoder.encode("中國", "UTF-8"));
response.addCookie(cookie);

//經過URLEncoding就要URLDecoding
String value = URLDecoder.decode(cookies[i].getValue(), "UTF-8");
複製程式碼

三、Session

在WEB開發中,伺服器可以為每個使用者瀏覽器建立一個會話物件(session物件),注意:一個瀏覽器獨佔一個session物件(預設情況下)
因此,在需要儲存使用者資料時,伺服器程式可以把使用者資料寫到使用者瀏覽器獨佔的session中,當用戶使用瀏覽器訪問其它程式時,其它程式可以從使用者的session中取出該使用者的資料,為使用者服務。

3.1、Session的原理

  1. 首先瀏覽器請求伺服器訪問web站點時,程式需要為客戶端的請求建立一個session的時候,伺服器首先會檢查這個客戶端請求是否已經包含了一個session標識、稱為SESSIONID
  2. 如果已經包含了一個sessionid則說明以前已經為此客戶端建立過session,伺服器就按照sessionid把這個session檢索出來使用,如果客戶端請求不包含session id,則伺服器為此客戶端建立一個session並且生成一個與此session相關聯的session id,sessionid 的值應該是一個既不會重複,又不容易被找到規律以仿造的字串,這個sessionid將在本次響應中返回到客戶端儲存,儲存這個sessionid的方式一般就是cookie。
  3. 這樣在互動的過程中,瀏覽器可以自動的按照規則把這個標識發回給伺服器,伺服器根據這個sessionid就可以找得到對應的session,又回到了步驟1。

3.2、Session的生命週期

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

恰恰是由於關閉瀏覽器不會導致session被刪除,迫使伺服器為seesion設定了一個失效時間,一般是30分鐘,當距離客戶端上一次使用session的時間超過這個失效時間時,伺服器就可以認為客戶端已經停止了活動,才會把session刪除以節省儲存空間。Session生成後,只要使用者繼續訪問,伺服器就會更新Session的最後訪問時間,無論是否對Session進行讀寫,伺服器都會認為Session活躍了一次,重新開始計算失效時間。

我們也可以自己來控制session的有效時間:

session.invalidate()將session物件銷燬
setMaxInactiveInterval(int interval) 設定有效時間,單位秒
複製程式碼

在web.xml中配置session的有效時間: 

<session-config>
<session-timeout>30</session-timeout> 單位:分鐘 
<session-config>
複製程式碼

所以,討論了這麼久,session的生命週期就是:
建立:Session儲存在伺服器端,一般放置在伺服器的記憶體中(為了高速存取),Sessinon在使用者訪問第一次訪問伺服器時建立,需要注意只有訪問JSP、Servlet等程式時才會建立Session,只訪問HTML、IMAGE等靜態資源並不會建立Session,可呼叫request.getSession(true)強制生成Session。
銷燬
1)超時,預設30分鐘
2)執行api:session.invalidate()將session物件銷燬、setMaxInactiveInterval(int interval) 設定有效時間,單位:秒
3)伺服器非正常關閉(自殺,直接將JVM馬上關閉)
如果正常關閉,session就會被持久化(寫入到檔案中,因為session預設的超時時間為30分鐘,正常關閉後,就會將session持久化,等30分鐘後,就會被刪除)
位置: D:\java\tomcat\apache-tomcat-7.0.53\work\Catalina\localhost\test01\SESSIONS.ser

3.3、session id的URL重寫

當瀏覽器將cookie禁用,基於cookie的session將不能正常工作,每次使用request.getSession() 都將建立一個新的session。達不到session共享資料的目的,但是我們知道原理,只需要將session id 傳遞給伺服器session就可以正常工作的。
解決:通過URL將session id 傳遞給伺服器:URL重寫
1)手動方式: url;jsessionid=....
2)api方式:

encodeURL(java.lang.String url) 進行所有URL重寫
encodeRedirectURL(java.lang.String url) 進行重定向 URL重寫
複製程式碼

這兩個用法基本一致,只不過考慮特殊情況,要訪問的連結可能會被Redirect到其他servlet去進行處理,這樣你用上述方法帶來的session的id資訊不能被同時傳送到其他servlet。這時候用encodeRedirectURL()方法就可以了。如果瀏覽器禁用cooke,api將自動追加session id ,如果沒有禁用,api將不進行任何修改。
注意:如果瀏覽器禁用cookie,web專案的所有url都需進行重寫。否則session將不能正常工作。
當cookie禁用時:

image.png

四、Session和Cookie的區別

4.1、從儲存方式上比較

Cookie只能儲存字串,如果要儲存非ASCII字串還要對其編碼。
Session可以儲存任何型別的資料,可以把Session看成是一個容器

4.2、從隱私安全上比較

Cookie儲存在瀏覽器中,對客戶端是可見的。資訊容易洩露出去。如果使用Cookie,最好將Cookie加密
Session儲存在伺服器上,對客戶端是透明的。不存在敏感資訊洩露問題。

4.3、從有效期上比較

Cookie儲存在硬碟中,只需要設定maxAge屬性為比較大的正整數,即使關閉瀏覽器,Cookie還是存在的
Session的儲存在伺服器中,設定maxInactiveInterval屬性值來確定Session的有效期。並且Session依賴於名為JSESSIONID的Cookie,該Cookie預設的maxAge屬性為-1。如果關閉了瀏覽器,該Session雖然沒有從伺服器中消亡,但也就失效了。

4.4、從對伺服器的負擔比較

Session是儲存在伺服器的,每個使用者都會產生一個Session,如果是併發訪問的使用者非常多,是不能使用Session的,Session會消耗大量的記憶體。
Cookie是儲存在客戶端的。不佔用伺服器的資源。像baidu、Sina這樣的大型網站,一般都是使用Cookie來進行會話跟蹤。

4.5、從瀏覽器的支援上比較

如果瀏覽器禁用了Cookie,那麼Cookie是無用的了!
如果瀏覽器禁用了Cookie,Session可以通過URL地址重寫來進行會話跟蹤。

4.6、從跨域名上比較

Cookie可以設定domain屬性來實現跨域名
Session只在當前的域名內有效,不可誇域名