天天看點

Session和Cookie一篇了解Session 和 cookie

Session 和 cookie

一、Cookie

​ Cookie是什麼呢?Cookie,有時也用其複數形式 Cookies。類型為“小型文本檔案”,是某些網站為了辨識使用者身份,進行Session跟蹤而儲存在使用者本地終端上的資料(通常經過加密),由使用者用戶端計算機暫時或永久儲存的資訊-----來自維基百科。用一句話來講,就是存儲在用戶端伺服器上的資料,是由網景公司(也就是這個公司發明了浏覽器哦)發明的一種網絡會話狀态跟蹤技術。

1.1 會話

​ 可能有人會提出疑問,網絡會話狀态又是什麼呢?首先我們要弄清網絡會話,會話,字面意思上就是一次交談,就用戶端A和服務端B就可以類比成兩個人小A和小B,一次會話就是AB之間的一次對話。如果用專業點的術語來講的話(●’◡’●),就是一次請求與響應。

​ 在一次請求和響應中,肯定是有資料傳遞的,是以這時,就需要會話狀态跟蹤 來檢視資料在這次會話中的狀态,但是在網絡層的Http協定是無狀态的。

小插曲:無狀态是什麼?

也就是當我們的小A和小B在進行通話完畢後,他們第二次又見面了,但是他們對上一次的會話一點都不記得了(當然現實中不太可能啦),也就是相當于丢失了在上次會話中的狀态。

​ 是以Cookie是由伺服器并存放在用戶端的一種資訊載體,存有這次會話的資訊,隻要Cookie沒有被清空,或者Cookie沒有失效,那麼會話狀态就是有效的。

1.2 Cookie在會話中的狀态

​ 使用者在第一次請求後,由伺服器生成Cookie,并将其封裝到響應頭中,以響應的方式發送給用戶端,用戶端接受到這個請求後,儲存到用戶端。當用戶端再次發同類請求,那麼就會将Cookie攜帶上,以此作為憑證,來通路服務端作校驗。

1.3 Cookie本質

​ 其實Cookie本質是多個Key-value鍵值對而已。但是針對不同的浏覽器,Cookie的儲存方式和儲存的位置都不一樣。

1.4 JavaEE下的Cookie

常用API
public class ServletDome extends HttpServlet {
    @Override
    protected  void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException{

        //利用唯一的構造函數狗雜Cookie
        Cookie cookie=new Cookie("key","value");
        //綁定這個Cookie是在哪個資源路徑下的,注意,這裡必須要綁定項目名稱
        cookie.setPath(req.getContextPath()+"/a/b");
        /**
         * @target         設定這個Cookie的過時時間,機關是秒
         *      如果時間大于0則需要将這個cookie存入外存中
         *          時間小于就是存在記憶體(緩存中),關閉頁面就消失
         *          時間等于0就是一旦産生就馬上失效
         */
        cookie.setMaxAge(60*60);
        //在HTTP Servlet Response中添加這個Cookie鍵值對
        resp.addCookie(cookie);
    }
}
           
public class ServletGetCookie extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //擷取請求中的Cookie資訊
        Cookie[] cookies=req.getCookies();
        for(Cookie c:cookies){
            System.out.println(c.getName()+"======="+c.getValue());
        }
    }
}
           

1.5 域屬性空間

總的來說一共有三個域屬性空間,在使用時優先肯定是使用小的,友善于保障資料的安全性,由大到小依次是:

  • ServletContext:

是屬于域的,可以完成跨會話的共享資料

  • HttpSession

    置入其中的域屬性是會話範圍的,可以完成同類請求下的通路共享資料

  • HttpServletRequest

    置入其實中的域屬性隻有在目前的請求路徑下,可以完成跨Servlet共享資料

二、Session

2.1 Session

​ Session也是一種會話狀态跟蹤技術。當然前面所講述的Cookie也是同樣目的的技術。但是兩者并不沖突,通常是将兩者進行混合使用,因為Session是将相關資料儲存在伺服器端的,并不是在用戶端。

​ Session是整個Web應用中所使用的,是以javax.servlet.http.HttpSession的接口對象的形式出現。

2.2 域屬性空間

Session,簡稱為域。其實也就是HttpSession,是可以進行跨請求的。

其中有三個方法可以對其資料進行寫和讀:

  • setAttribute(Stirng name,Object value)

    用于存放資料

  • getAttribute(String name)

    用于擷取Value

  • removeAttribute(String name)

    用于删除

2.3 Sesion的具體使用

public class SomeServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
        //擷取使用者送出的參數
        String username=request.getParameter("username");

        //将參數放入request域
        request.setAttribute("user",username);

        //擷取Session對象
        HttpSession session=request.getSession(false);

        //在session域中寫入屬性
        session.setAttribute("username",username);

        response.getWriter().print("SomeServlet: "+username);
    }
}
           
public class OtherServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        String user=req.getParameter("user");

        //擷取Session
        HttpSession session=req.getSession(false);

        //從Session中讀取指定屬性
        String username=null;
        if (session!=null){
            username= (String) session.getAttribute("username");
        }
        PrintWriter out=resp.getWriter();
        out.print("OtherServlet:user: "+user);
        out.print("OtherServlet:username: "+username);
    }
}
           

2.4 Session工作原理

在系統中會對每一個會話維護一個Session會話,這裡擴充下前面的域屬性空間,其中,跨域,是指可以跨越不同的伺服器;跨請求,是指可以跨越不同的工程;跨Servlet是指可以跨越不同的具體資源。(HttpSession的具體實作類是在Tomcat中的)

  • 寫入Session清單

    伺服器對目前的Session是以Map管理的,也就是Session清單

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-mltw3ewn-1588090079713)(D:\App\Typora\resources\md-image\Session和Cookie\image-20200428222809253.png)]

key是以32位長度的随機串,被稱作JSessionID

value是Session對象的引用

當使用者第一次送出請求時,服務端Servlet中執行request.getSession()後,會自動生成一個Map.Entry對象,然後存入key-value;

  • 伺服器生成并發送Cookie

    在服務端存入了相應的Session資訊後,系統還會自動将“JSESSIONID”作為key,sessionid作為value,放到response的頭中去,并存入用戶端,這個也就是Cookie。

  • 用戶端接受并發送Cookie

    用戶端将接受到的JSESSIONID這個Cookie放入緩存中,當使用者第二次通路的時候,會将緩存中這個Cookie,伴随着請求頭的頭部資訊,一起發送出去。

2.5 Session的失效

我們在平時會發現,當我們長時間不去登入一個網站後,本來會自動顯示的賬号提示資訊會消失不見(這個資訊也是由session存放的)。其實這個因為Session失效了。那麼什麼是失效呢?

首先,我們可以在web.xml中設定session的逾時時間(默默提一句,為什麼是在web.xml中設定,因為HttpSession的具體實作類是在Tomcat中實作的)

<session-config>
    <!--以分鐘為機關-->
    <session-timeout>10</session-timeout>
</session-config>
           

或者在Java代碼中,拿到session對象調用invalidate方法

那麼什麼時候會失效呢?我們把頁面關了算不算以及失效了呢?在平時我們總是這樣認為,但其實并不是。在上面我們已經知道session的真正引用會存儲在服務端,是以當我們沒用Cookie這個憑證時,我們直接拿那32位的門票進去也可以擷取到那個Session的引用。是以隻有當我們等服務端的session真正失效後才總算是真正安全的。

2.6 重定向和轉發的番外

當我們在禁用Cookie後,上面提到了,我們扔可以通過JSeesionID來擷取到Session對象。但是當我們重定向時禁掉Cookie時怎麼擷取那個重定向後的資料呢?我們可以encode來自動通過上面的方法來通路重定向後的禁用掉Cookie的網站

String url=req.getContextPath()+"someSevlet";
url=resp.encodeRedirectURL(url);
resp.sendRedirect(url);
           

轉發也是如此,隻是調用的函數不同罷了:

String url=req.getContextPath()+"someSevlet";
url=resp.encodeURL(url);
resp.sendRedirect(url);
)+"someSevlet";
url=resp.encodeRedirectURL(url);
resp.sendRedirect(url);
           

轉發也是如此,隻是調用的函數不同罷了:

String url=req.getContextPath()+"someSevlet";
url=resp.encodeURL(url);
resp.sendRedirect(url);