cookie&session

1.會話技術

1.1會話技術概述

         會話可簡單理解爲:用戶打開一個瀏覽器,點擊多個超鏈接,訪問服務器多個web資源,然後關閉瀏覽器,整個過程稱之爲一個會話。

1.2 會話技術的分類

(1)cookie:

    Cookie是客戶端技術,翻譯成中文是小甜點。在HTTP中它表示服務器送給客戶端瀏覽器的小甜點。其實Cookie就是一個鍵和一個值構成的,隨着服務器端的響應發送給客戶端瀏覽器。然後客戶端瀏覽器會把Cookie保存起來,當下一次再訪問服務器時把Cookie再發送給服務器。Cookie是由服務器創建,然後通過響應發送給客戶端的一個鍵值對。客戶端會保存Cookie,並會標註出Cookie的來源(哪個服務器的Cookie)。當客戶端向服務器發出請求時會把所有這個服務器Cookie包含在請求中發送給服務器,這樣服務器就可以識別客戶端了。

(2)session:

    Session是服務器端技術,利用這個技術,服務器在運行時可以爲每一個用戶的瀏覽器創建一個其獨享的session對象,由於session爲用戶瀏覽器獨享,所以用戶在訪問服務器的web資源時,可以把各自的數據放在各自的session中,當用戶再去訪問服務器中的其它web資源時,其它web資源再從用戶各自的session中取出數據爲用戶服務。

2.cookie

2.1 cookie概述

         Cookie是由服務器端生成,發送給User-Agent(一般是瀏覽器),瀏覽器會將Cookie的key/value保存到某個目錄下的文本文件內,下次請求同一網站時就發送該Cookie給服務器(前提是瀏覽器設置爲啓用cookie)。Cookie名稱和值可以由服務器端開發自己定義,對於JSP而言也可以直接寫入jsessionid,這樣服務器可以知道該用戶是否合法用戶以及是否需要重新登錄等,服務器可以設置或讀取Cookies中包含信息,藉此維護用戶跟服務器會話中的狀態。


2.2 cookie與Http協議

(1)cookie與http協議關係

    Cookie是Http協議制定的,並不是Java語言獨有的,PHT、.NET中也使用了cookie技術,因此只要是和HTTP協議相關,那麼就可以使用cookie技術。

    cookie是服務器創建的一個鍵值對,並保存在瀏覽器端。在服務器端先創建cookie,如 Cookie cookie=newCookie(String name,String value),其中Cookie可以在javaeeAPI中查到的,詳情可參考java_ee API。然後再通過response對象將cookie信息作爲響應頭髮送到瀏覽器端。我們可以通過抓包工具查看響應信息,可以發現cookie是基於一個Set-Cookie響應頭工作的,由於Set-Cookie響應頭可以有多個,所以我們可以通過response.addHeader(Stringname,String value)方法發送Set-Cookie響應頭,例如,有兩個cookie,分別爲one=aaa,two=bbb,其中one、two是cookie的名稱,aaa、bbb是cookie的值。發送響應頭如下所示:

    response.addHeader(“Set-Cookie”,”one=aaa”);

    response.addHeader(“Set-Cookie”,”two=bbb”);

    當瀏覽器再次訪問服務器時,會將cookie送還給服務器。瀏覽器通過Cookie請求頭傳遞過去,請求頭Cookie與響應頭Set-Cookie有區別,多個cookie對應多個Set-Cookie響應頭,但是隻對應一個Cookie請求頭,格式爲:Cookie:one=aaa; two=bbb。即多個cookie之間用分號和空格隔開。

需要注意的是:cookie是不能跨瀏覽器的。例如,張三首先使用IE瀏覽器訪問服務器,服務器發送了一個cookie,這個cookie只會保存在IE瀏覽器,如果再使用火狐瀏覽器訪問服務器,服務器會再發送一個cookie個火狐瀏覽器,在火狐瀏覽器中不能獲取IE瀏覽器中的cookie,同理IE瀏覽器也獲取不到火狐瀏覽器中的cookie。

(2)http協議規定

    Http協議對Cookie做了一些規定,如下所示:

    a.   一個Cookie的大小,最大爲4KB;

    b.   一個服務器最多向一個瀏覽器保存20個Cookie;

    c.    一個瀏覽器最多可以保存300個Cookie。

2.3 cookie常用方法

    javax.servlet.http.Cookie類用於創建一個Cookie,response接口也中定義了一個addCookie方法,它用於在其響應頭中增加一個相應的Set-Cookie頭字段。 同樣,request接口中也定義了一個getCookies方法,它用於獲取客戶端提交的Cookie。

構造方法:

    public  Cookie(String name, String value):構造帶指定名稱和值的 cookie。

成員方法:

    public  String  getName():返回 cookie 的名稱

    public  String  getValue():返回 cookie 的值。

    public  void  setMaxAge(int expiry):設置 cookie 的最大生存時間,以秒爲單位

    public  void  setPath(String uri):指定客戶端應該返回 cookie 的路徑。

        

第一次請求和響應信息:

        

第二次請求與響應信息:


2.4 cookie的持久化

        如果創建了一個cookie,並將他發送到瀏覽器,默認情況下它是一個會話級別的cookie(即存儲在瀏覽器的內存中),用戶退出瀏覽器之後即被刪除。若希望瀏覽器將該cookie存儲在磁盤上,則需要使用Cookie類的setMaxAge方法,並給出一個以秒爲單位的時間。

    (1)cookie.setMaxAge(-1):cookie的maxAge屬性的默認值就是-1,表示只在瀏覽器內存中存活。一旦關閉瀏覽器窗口,那麼cookie就會消失。

    (2)cookie.setMaxAge(60*60):表示cookie對象可存活1小時。當生命大於0時,瀏覽器會把Cookie保存到硬盤上,就算關閉瀏覽器,就算重啓客戶端電腦,cookie也會存活1小時;

    (3)cookie.setMaxAge(0):cookie生命等於0是一個特殊的值,它表示cookie被作廢!也就是說,如果原來瀏覽器已經保存了這個Cookie,那麼可以通過Cookie的setMaxAge(0)來刪除這個Cookie。無論是在瀏覽器內存中,還是在客戶端硬盤上都會刪除這個Cookie。

2.5cookie的路徑

    (1)什麼是Cookie的路徑

        WEB應用A,向客戶端發送了10個Cookie,這就說明客戶端無論訪問應用A的哪個Servlet都會把這10個Cookie包含在請求中!但是也許只有AServlet需要讀取請求中的Cookie,而其他Servlet根本就不會獲取請求中的Cookie。這說明客戶端瀏覽器有時發送這些Cookie是多餘的!可以通過設置Cookie的path來指定瀏覽器,在訪問什麼樣的路徑時,包含什麼樣的Cookie。

    (2)Cookie路徑與請求路徑的關係

    Cookie路徑的作用:

        下面是客戶端瀏覽器保存的3個Cookie的路徑:

        a:/cookietest;

        b:/cookietest/servlet;

        c:/cookietest/jsp;

 

        下面是瀏覽器請求的URL:

        A:http://localhost:8080/cookietest/AServlet;

        B:http://localhost:8080/cookietest/servlet/BServlet;

        C:http://localhost:8080/cookietest/jsp/CServlet;

        請求A時,會在請求中包含a;

        請求B時,會在請求中包含a、b;

        請求C時,會在請求中包含a、c;

          也就是說,請求路徑如果包含了Cookie路徑,那麼會在請求中包含這個Cookie,否則不會請求中不會包含這個Cookie。

               A請求的URL包含了“/cookietest”,所以會在請求中包含路徑爲“/cookietest”的Cookie;

     B請求的URL包含了“/cookietest”,以及“/cookietest/servlet”,所以請求中包含路徑爲“/cookietest”和“/cookietest/servlet”兩個Cookie;

     B請求的URL包含了“/cookietest”,以及“/cookietest/jsp”,所以請求中包含路徑爲“/cookietest”和“/cookietest/jsp”兩個Cookie;

    (3)設置Cookie的路徑

        設置Cookie的路徑需要使用setPath()方法,例如:

        cookie.setPath(“/cookietest/servlet”);

 

    如果沒有設置Cookie的路徑,那麼Cookie路徑的默認值當前訪問資源所在路徑,例如:

    訪問http://localhost:8080/cookietest/AServlet時添加的Cookie默認路徑爲/cookietest;

    訪問http://localhost:8080/cookietest/servlet/BServlet時添加的Cookie默認路徑爲/cookietest/servlet;

    訪問http://localhost:8080/cookietest/jsp/BServlet時添加的Cookie默認路徑爲/cookietest/jsp;

2.6 Cookie中保存中文

        Cookie的name和value都不能使用中文,如果希望在Cookie中使用中文,那麼需要先對中文進行URL編碼,然後把編碼後的字符串放到Cookie中。

(1)向客戶端響應中添加Cookie

        String name = URLEncoder.encode("姓名", "UTF-8");

       String value = URLEncoder.encode("張三", "UTF-8");

       Cookie c = new Cookie(name, value);

       c.setMaxAge(3600);

       response.addCookie(c);

(2)從客戶端請求中獲取Cookie

        response.setContentType("text/html;charset=utf-8");

       Cookie[] cs = request.getCookies();

       if(cs != null) {

           for(Cookie c : cs) {

              String name = URLDecoder.decode(c.getName(), "UTF-8");

              String value = URLDecoder.decode(c.getValue(), "UTF-8");

              String s = name + ": " + value + "<br/>";

              response.getWriter().print(s);

           }

       }

3. session

3.1 session概述

        HttpSession是javax.servlet.http包下的一個接口,用來進行會話跟蹤。HttpSession對象是Servlet的三大域對象之一,其他兩個域對象是HttpServletRequest和ServletContext。這三個域中,request的域範圍最小,它的域範圍是整個請求鏈,並且只在請求轉發和包含時存在;session域對象的域範圍是一次會話,而在一次會話中會產生多次請求,因此session的域範圍要比request大;application的域範圍是最大的,因爲一個web應用只有唯一的一個application對象,只有當web應用被移出服務器或服務器關閉它才死亡,它的域範圍是整個應用。

3.2 session常用方法

    (1)voidsetAttribute(String name,Object value):向域中添加域屬性;

    (2)ObjectgetAttribute(String name):從域中獲取指定名稱的屬性值;

    (3)VoidremoveAttribute(String name):移出域中指定名稱的域屬性

Session相關方法:

    (a)String getId():獲取sessionId;

    (b)intgetMaxInactiveInterval():獲取session可以的最大不活動時間(秒),默認爲30分鐘。當session在30分鐘內沒有使用,那麼Tomcat會在session池中移除這個session;

    (c)voidsetMaxInactiveInterval(int interval):設置session允許的最大不活動時間(秒),如果設置爲1秒,那麼只要session在1秒內不被使用,那麼session就會被移除;

    (d)long getCreationTime():返回session的創建時間,返回值爲當前時間的毫秒值;

    (e)longgetLastAccessedTime():返回session的最後活動時間,返回值爲當前時間的毫秒值;

    (f)voidinvalidate():讓session失效!調用這個方法會被session失效,當session失效後,客戶端再次請求,服務器會給客戶端創建一個新的session,並在響應中給客戶端新session的sessionId;

    (g)booleanisNew():查看session是否爲新。當客戶端第一次請求時,服務器爲客戶端創建session,但這時服務器還沒有響應客戶端,也就是還沒有把sessionId響應給客戶端時,這時session的狀態爲新。

3.3 session對象的獲取

        如果請求時,cookie中有jsessionid這個cookie,那麼request.getSession()就會根據jsessionid值查找session的id,如果查找到,會使用已有的,如果沒有查找到,會創建。

        如果請求時,cookie中沒有jsessionid這個cookie,那麼request.getSession()就會創建一個新的session對象.

3.4 session實現原理

         session底層是依賴Cookie,當首次使用session時,服務器端要創建session,session是保存在服務器端,而給客戶端的session的id(一個cookie中保存了sessionId)。客戶端帶走的是sessionId,而數據是保存在session中。

        當客戶端再次訪問服務器時,在請求中會帶上sessionId,而服務器會通過sessionId找到對應的session,而無需再創建新的session。


3.5 session對象的銷燬分析

瀏覽器關閉了,session對象不會銷燬的,session的銷燬與關閉瀏覽器無關.

session對象銷燬方式:

         (1)關閉服務器         

         (2)默認超時              

                  在tomcat/conf/web.xml文件中設置了session默認超時時間

                     <session-config>

                                   <session-timeout>30</session-timeout>

                          </session-config>                   

                  默認30分鐘超時         

         (3)可以設置session超時時間(以秒爲單位)

                   void setMaxInactiveInterval(int interval) 

         (4)銷燬session

                  invalidate();

3.6 session失效

     session失效有如下幾個原因:

        (1)客戶端的請求中沒有sessionId。可能是因爲這是第一次請求(開始一個新的會話),也可能是服務器設置Cookie的maxAge爲0導致的;

        (2)客戶端請求中存在sessionId,但這個sessionId在session池中沒有匹配的session對象。這可能是因爲session太久沒有使用,服務器把session從池中移除的原因;

        (3)客戶端請求中存在sessionId,但匹配的session對象被標記爲失效!這可能是因爲服務器調用了session.invalidate()方法導致的。

4. URL重寫

4.1 URL重寫概述

        如果瀏覽器不支持Cookie或用戶阻止了所有Cookie,可以把會話ID附加在HTML頁面中所有的URL上,這些頁面作爲響應發送給客戶。這樣,當用戶單擊URL時,會話ID被自動作爲請求頭的一部分而不是作爲頭行發送回服務器。這種方法稱爲URL重寫(URL rewriting)。

4.2 URL重寫的作用

        當客戶機不接受cookie時,server就使用URL重寫作爲會話跟蹤的基本方式,URL重寫,添加了附加數據(會話ID)到請求的URL路徑上。 會話ID必須被編碼作爲該URL字符串中的路徑參數。該參數的名稱爲jsessionid,簡單說就是cookie禁用了jsessionid就不能攜帶,那麼每次請求,都是一個新的session對象。如果想要使用同一個session對象,可以使用url重寫.

         response.encodeRedirectURL(java.lang.String url)

                  用於對sendRedirect方法後的url地址進行重寫。

         response.encodeURL(java.lang.String url)

                  用於對錶單action和超鏈接的url地址進行重寫
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章