一文快速回顧 Session 和 Cookie

2023-03-11 06:00:29

前言

在 Web 應用程式中(通俗點,可以理解成一個網站),Session 和 Cookie 是兩個非常重要的概念,主要用於實現使用者身份認證、資料傳遞等功能。今天就來講講這兩個東西。

對於當時剛開始接觸到這兩個概念的我來說,這兩個東西是非常模糊的,當然,這樣也和我自己 Java 基礎不牢固有關,導致在學習 Java Web 的過程中,埋下了許多地雷。現如今,從新梳理下,希望能給螢幕前的你帶來收穫。

本篇文章目標人群是學了後忘了的,學了後想要鞏固的。當然,還沒學,那就更好啦,直接看這一篇就夠了!

Session 的概念

Session 是 Web 應用程式中的一種對談管理機制,用於儲存和維護使用者的對談狀態。

那問題來了,什麼是「對談」?

對談是指在使用者與伺服器之間的一系列請求和響應之間的互動過程。

當用戶存取 Web 應用時,伺服器會建立一個唯一的對談 ID,並將其儲存在使用者的瀏覽器中的 Cookie 中。在接下來的請求中,瀏覽器會將對談 ID 作為引數傳送給伺服器,以便伺服器可以識別使用者並將其請求與之前的請求相關聯。

為什麼會有 Session?

由於 HTTP 協定是無狀態的,當用戶在網站中進行多次請求,伺服器並不能判斷這些請求是不是來自同一使用者,所以出現了一種技術,這種技術稱為「對談跟蹤技術」。

對談跟蹤技術就能解決這個問題。與無狀態的通訊相比,對談是一種有狀態的通訊,這種通訊至少需要一方來維護當前的狀態資訊和歷史資訊。

Session 就是其中一種對談跟蹤技術,當然,後面說的 Cookie 也是。

,並將 Session ID 儲存在 Cookie 中或者 URL 引數中。

Session 的原理

Session 的原理是基於伺服器端的儲存和管理,因此相對來說比較安全。在使用者存取 Web 應用程式時,伺服器會為每個使用者建立一個唯一的 Session ID,伺服器會將 Session ID 和對應的對談狀態儲存在記憶體或者資料庫中,同時也返回一份 Session ID 給瀏覽器,讓瀏覽器儲存在 Cookie 中,並在一定時間內保持有效。當用戶進行後續的請求時,伺服器會根據 Session ID 來識別使用者,並獲取和維護使用者的對談狀態。最後,當用戶關閉瀏覽器或者超過一定時間沒有活動時,伺服器會自動銷燬對應的 Session。

Session 的優點是安全性相對較高,儲存容量可以儲存任意資料型別,並且可以設定失效時間。但是它也存在一些缺點:

  • 儲存在伺服器端,需要佔用伺服器資源(比如記憶體資源)
  • 失效時間短,一般只有數分鐘或數小時
  • 難以跨域共用,不同域名的伺服器無法共用 Session

程式碼如何寫?

那伺服器這邊是怎樣去儲存和管理的呢?程式碼是怎樣寫的呢?

在 Java Web 中,可以使用 Servlet API 中封裝好的 Session 物件(HttpSession)來進行操作。

在Servlet API中,HttpSession 由 Servlet容器(比如 Tomcat)建立,它可以儲存任意的 Java 物件,我們可以通過 setAttribute() 方法將物件繫結到 Session 中,之後通過 getAttribute() 方法獲取繫結在 Session 中的物件。

也就是說,可以在一次對談的多次請求間共用資料,將資料儲存在伺服器端的物件中。

  • 獲取 Session 物件

我們可以通過 HttpServletRequest 的 getSession() 方法來獲取 HttpSession 物件。如果 HttpSession 物件不存在,則會建立一個新的 Session 物件。

Session 常用方法

以下是一些常用的 Session 物件的方法:

  • setAttribute(String name, Object value):將一個名為 name,值為 value 的物件繫結到 Session 中。

  • getAttribute(String name):獲取 Session 中繫結的名為 name 的物件。

  • removeAttribute(String name):從 Session 中刪除名為 name 的物件。

  • getId():獲取 Session 的唯一識別符號。

  • getCreationTime():獲取 Session 的建立時間。

  • getLastAccessedTime():獲取 Session 的最後存取時間。

  • setMaxInactiveInterval(int interval):設定 Session 的最大不活動時間間隔,單位為秒。

  • getMaxInactiveInterval():獲取 Session 的最大不活動時間間隔。

範例程式碼:

SessionServlet

@WebServlet(name = "SessionServlet", urlPatterns = "/session")
public class SessionServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 獲取 Session 物件
        HttpSession session = req.getSession();
        // 將使用者名稱儲存到 Session 中
        session.setAttribute("username", req.getParameter("username"));
        // 重定向到另一個頁面
        resp.sendRedirect("anotherPage.jsp");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

這裡使用了 @WebServlet 來設定這個 Servlet,處理的請求對映的路徑為 /session,主要進行了 Session 物件的相關操作,儲存了使用者資訊,重定向到另一個頁面,通過 Session,此時在另一個頁面,就能夠獲取到儲存的資訊。

anotherPage.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page session="true" %>
<html>
<head>
    <title>這裡是有Session的</title>
</head>
<body>
    <%
        String username = (String) session.getAttribute("username");
    %>
    <h2>從Session中獲取的資訊:<%=username%></h2>
</body>
</html>

生成唯一 ID 返回給瀏覽器

@WebServlet(name = "SessionIdServlet", urlPatterns = "/sessionId")
public class SessionIdServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        // 獲取 SessionID
        String sessionId = session.getId();
        // 建立名為JSESSIONID的 Cookie
        Cookie cookie = new Cookie("JSESSIONID", sessionId);
        // 設定 Cookie 效時間為30分鐘
        cookie.setMaxAge(30 * 60);
        // 將 Cookie 追加到響應中返回給瀏覽器
        resp.addCookie(cookie);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

通過瀏覽器向這個路徑 /sessionId 發起請求,就會接收到伺服器返回的響應,這裡的響應就有我們進行處理的名為 JSESSIONID 的 Cookie

Cookie 和 Session 總是會被拿來比較的。Cookie 和 Session 都是用來跟蹤瀏覽器使用者身份的對談技術,或者說一種機制。它們都可以實現在多個頁面之間共用使用者的狀態。

Cookie 是一種在使用者端(瀏覽器)儲存資料的機制。

瀏覽器第一次傳送請求到伺服器,伺服器就建立 Cookie(上面的程式碼中我們寫了),該 Cookie 中包含著資訊,可以是使用者的資訊(使用者偏好設定、廣告偏好),然將該 Cookie 傳送到瀏覽器。

瀏覽器之後再次存取伺服器時就會攜帶伺服器建立的 Cookie,這不需要我們做任何操作,不需要寫任何程式碼,瀏覽器幫我們實現了在每一次的請求中都攜帶上 Cookie。伺服器端通過 Cookie 中攜帶的資料區分不同的使用者。

Cookie 的優點是可以長時間儲存,並且可以在使用者端設定,但是它也存在一些缺點:

  • 安全性相對較差,容易被不法分子獲取
  • 儲存容量有限,一般只能儲存 ASCII 碼
  • 失效時間可以設定,但是使用者端可以隨時清除 Cookie

總結

Session 是一種伺服器端的儲存機制,它將使用者狀態資訊儲存在伺服器上,每個使用者都有一個獨立的 Session。

在使用者第一次存取伺服器的時候,伺服器會為其建立一個 Session,並將 Session ID 放到一個名為 JSESSIONID 的 Cookie 中傳送給瀏覽器。

Cookie 是一種使用者端(瀏覽器)儲存機制,它將使用者狀態資訊儲存在使用者端瀏覽器上。我們知道,使用者第一次存取伺服器的時候,伺服器會將一些資料(比如 JSESSIONID)寫入 Cookie 並行送給使用者端,使用者端在後續的請求中會將 Cookie 傳送給伺服器。

在儲存容量方面,Cookie 的儲存容量較小,一般只能儲存 ASCII 碼,而 Session 可以儲存任意資料型別。在安全性方面,Session 相對於 Cookie 更加安全,因為 Session 儲存在伺服器,使用者端無法直接存取。在跨域共用方面,Cookie 可以跨域共用,而 Session 只能在同一域名下共用。

最後的最後

由本人水平所限,難免有錯誤以及不足之處, 螢幕前的靚仔靚女們 如有發現,懇請指出!

最後,謝謝你看到這裡,謝謝你認真對待我的努力,希望這篇部落格對你有所幫助!

你輕輕地點了個贊,那將在我的心裡世界增添一顆明亮而耀眼的星!