【Java Web】提问:谈谈你对Cookie与Session的理解,并分析二者的区别

一、前言

在Web开发中,用户会话管理是至关重要的,它使服务器能够跟踪用户的状态和提供个性化的服务。

两种常见的用户会话管理方式是使用浏览器Cookie和服务器端Session对象。本文将探索这两种方法的工作原理以及如何在Servlet中使用它们进行用户会话管理。


二、内容

HTTP协议本身是无状态的,这意味着每次客户端与服务器之间的通信都是独立的,没有持久的连接。当客户端发送请求后,服务器会响应,然后关闭连接,不会保留有关先前请求的信息。这就意味着,同样的客户,第一次发送请求和第N次发送请求来讲,服务器都会认为是一个新的用户。HTTP请求是单向的,只有客户端(浏览器)向服务器发送请求,服务器不能主动向客户端发送数据,因此服务器通常难以识别不同请求的身份。

然而,人们在浏览网页的过程中很快发现如果能够提供一些按需生成的动态信息会使 Web 变得更加有用,就像客户在登录购物网站后,记录客户登录网站的信息;需要结账时,需要看他之前买过什么。随着时间的推移,人们对更多的互动和动态内容产生了需求。为了收集用户数据和支持用户与网页的互动,HTML引入了表单元素,允许用户输入信息并将其发送到服务器。同时,JavaScript等脚本语言的引入使得网页可以动态地响应用户的操作。HTTP也经历了演进,引入了新的特性。

Cookie是在这种背景下发挥作用的。它实际上是一小段文本信息,以键值对的格式组织。当服务器需要记录特定请求的身份信息或用户状态时,它会向客户端颁发一个Cookie。客户端在以后的请求中将这个Cookie与请求一起发送给服务器。服务器可以检查该Cookie以确认用户身份和状态

Cookie是一种在用户计算机上存储的小型文本文件,通常由网站服务器通过浏览器发送给用户的设备,然后浏览器会将其保存在本地。注意,Cookie 具有时效性,其内容会伴随着请求发送给服务器。

Cookie指的是网站为了辨别用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)。我们也可以叫浏览器缓存。

(3)Cookie 的工作流程

那么,当我们第一次访问并登录一个网站的时候,Cookie的设置会经历以下几个步骤:

  1. 客户端发送请求到服务器: 当首次访问一个网站并尝试登录时,浏览器会向服务器发送HTTP请求以请求登录页面或验证身份。
  2. 服务器返回响应+Set-Cookie字段: 服务器会处理您的请求,如果您成功登录,服务器会在HTTP响应头中包含一个名为"Set-Cookie"的字段。这个字段包含一个或多个Cookie,通常是键值对,用于标识您的会话或保存其他相关信息。
  3. 客户端保存Cookie: 浏览器接收到响应后,会自动解析"Set-Cookie"字段,并将Cookie保存在本地的Cookie存储中,通常是在浏览器的Cookie文件中。
  4. 客户端再向服务器发送请求时,会自动将Cookie添加到请求头中: 当我们以后再次访问该网站的其他页面或执行其他操作时,浏览器会自动将相关的Cookie添加到HTTP请求头中,以便与服务器通信。这使得服务器可以识别您的身份和会话状态。
  5. 服务器辨识出请求身份信息,直接发送数据: 服务器在接收到包含Cookie的请求后,会检查Cookie中的信息,以辨识用户身份和会话状态。服务器可以根据这些信息为用户提供个性化的服务或允许用户访问其账户相关数据。这样,服务器可以识别用户,无需用户在每个请求中重新进行登录操作。

(4)如何在Servlet中使用Cookie?

Servlet 中,Java 把Cookie封装成了javax.servlet.http.Cookie类,每个Cookie都是该Cookie类的对象。服务器通过操作Cookie类对象对客户端Cookie进行操作。通过response.addCookie(Cookiecookie)向客户端设置Cookie,通过request.getCookie()获取客户端提交的所有Cookie(以Cookie[]数组形式返回)。

下面是一些常用的Cookie类方法:

方法 描述
public void setMaxAge(int expiry) 设置cookie的最大生命周期(以秒为单位)
public String getName() 返回cookie的名称。创建后无法更改名称
public String getValue() 返回cookie的值
public void setName(String name) 更改cookie的名称
public void setValue(String value) 更改cookie的值

下面举一个简单的例子,比如要实现七天内登录有效的功能。

这里假设工程名字为 firstServlet

我们首先在 LoginServlet 中进行如下设置:

java 复制代码
@WebServlet("/cookies/login")
public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    public LoginServlet() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // ......
        System.out.println("用户登录成功");
        // 创建 cookie
        Cookie cookie = new Cookie("User" , "admin");
        // 设置 cookie 7天后失效(这里以秒为单位)
        cookie.setMaxAge(60 * 60 * 24 * 7);
        // 将 cookie 添加到响应对象中
        response.addCookie(cookie);
        // 打印提示信息
        response.getWriter().println("login success");
    }
}

现在,我们就可以在 IndexServlet 中进行 cookie 信息的读取:

java 复制代码
@WebServlet("/cookies/index")
public class IndexServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public IndexServlet() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // request.getCookies() 用于获取所有的Cookie,返回值是一个 Cookie[] 数组
        Cookie[] cs = request.getCookies();
        if (cs == null) {
            response.getWriter().println("user not login");
            return;
        }
        // 一个简单的用户登录判断逻辑
        String user = null;
        for (Cookie c : cs) {
            System.out.println(c.getName() + ":" + c.getValue());
            if (c.getName().equals("User")) {
                user = c.getValue();
                break;
            }
        }
        if (user == null) {
            response.getWriter().println("user not login");
        } else {
            response.getWriter().println("User:" + user);
        }
	}

}

代码写完后,我们启动服务器,看看效果。

我们首先访问网站首页:

访问地址为:

bash 复制代码
http://localhost:8080/firstServlet/cookies/index

很显然,此时用户并未登录。

接下来,我们进行用户登录请求(简单模拟),访问以下地址:

bash 复制代码
http://localhost:8080/firstServlet/cookies/login

接着,我们再访问首页:

此时,我们就可以访问到用户登录的信息了。


2.2 Session

在上文中,我们认识了 cookies,它是浏览器端保存在我们电脑上的数据。现在,我们再来看一个新的知识点。会话对象Session

(1)什么是 Session ?

session是基于Cookie技术应用的HTTP扩展结构,Session 机制是另一种在客户端与服务器之间保持状态的解决方案,它的特殊点在于,它是存储在服务器端

session 是另一种记录客户状态的机制,是一次客户端(浏览器)与服务器交互的会话。

什么是会话?

浏览器请求一次服务器,服务器接收请求,处理之后,给出响应,这就是一次会话。

"有时候长时间不登录会直接跳出登录状态,这是因为,cookie 保存了 sessionId, 后台缓存是需要付出内存代价的,一 般有超时时间,默认 30 分钟,一旦超时,后台 session 自动销毁,前台 cookie 里面保存的 sessionId 就会失效,再次访问后台验证时候,程序会让重新登录,产生新的 session。"

好了,我们来总结一下。所谓的 Session ,其实就是服务器端的数据存储,用于在用户与服务器之间保持状态信息。每个用户会话都有一个唯一的Session ID,该ID通常存储在Cookie中,用于在服务器上查找与该用户关联的数据

(2)有了Cookie,为什么还需要session呢?

我们知道,Cookies 是在客户端(浏览器)中存储的小段文本数据,用于跟踪用户的会话信息、持久化登录状态等。是一种在客户端维护状态信息的有效方式。Cookies可以长时间存储,即使用户关闭浏览器后再次访问网站时,它们仍然可用。

那既然 Cookies 如此有效,为什么还需要 Session呢?

我们来看一下 Cookies 的限制:

  1. Cookies的容量有限,通常每个Cookie的大小受到限制,因此不适合存储大量数据。
  2. Cookies的内容可被浏览器访问和修改,因此不适合存储敏感信息(有被破解的可能)。

由于 web 项目必须建立存储安全可靠,能存对象,且数据量较大的内存模型,此时就需要有类似 session 技术了。Session适用于存储大量、敏感或临时性的数据,因为数据存储在服务器上。Session可以提供更高的安全性,因为客户端无法直接访问或修改Session数据。

session是服务器端的技术。服务器为每一个浏览器开辟一块内存空间。一般情况下,服务器会在一定时间内(默认30分钟)保存这个 Session,过了时间限制,就会销毁这个Session。在销毁之前,程序员可以将用户的一些数据以Key和Value的形式暂时存放在这个 Session中。

(3)操作 Session 对象

在Servlet中,我们可以使用以下代码来创建一个Session对象:

java 复制代码
// 创建或获取一个Session对象
HttpSession session = request.getSession();

使用Session对象来存储用户特定的数据,如用户ID、用户名等:

java 复制代码
session.setAttribute("userId", 12345);
session.setAttribute("username", "admin");

通过键来检索Session中存储的数据:

java 复制代码
Integer userId = (Integer)session.getAttribute("userId");
String username = (String)session.getAttribute("username");

举一个例子,比如我们现在有两个 Servlet 。一个是 SessionLoginServlet,另一个是 SessionIndexServlet

SessionLoginServlet是一个模拟用户登录的 Servlet 。当用户访问这个Servlet时,它会创建一个Session对象,并在Session中存储名为 "name" 的属性,值为 "李四"。然后,它将请求重定向到 SessionIndexServlet。这是首页的Servlet,用于显示登录用户名。SessionIndexServlet将从Session中检索名为 "name" 的属性,并在响应中显示当前登录用户的用户名。

当用户首次访问 SessionLoginServlet 时,它会将 "name" 属性存储在Session中,然后用户被重定向到 SessionIndexServletSessionIndexServlet 从Session中检索 "name" 属性,并显示在首页上。

如下所示:

(4)session.setAttribute 和 request.setAttribute的区别

从生命周期的角度出发:

存储在session对象中的属性的生命周期更长。它们会一直存在,直到会话(session)结束或会话超时,或者通过编程方式从会话中删除。而存储在request对象中的属性只在一次请求-响应周期内有效。这意味着只有在处理当前请求的过程中才可以访问这些属性,一旦响应返回给客户端,这些属性将被销毁。

从作用域的角度出发:

存储在session对象中的属性,其作用域更广泛,它们可以被同一个用户的不同请求所共享,只要这些请求属于同一个会话。这使得它们适用于在会话之间共享数据,例如用户登录信息或购物车内容。而后者设置的属性则局限在当前请求中,因此它们只能在当前请求的处理过程中访问。


三、总结

本文探讨了浏览器Cookie和Servlet中的Session对象,它们分别用于在Web应用程序中管理用户会话。

Cookie是一种在用户浏览器端存储的小型文本文件,用于在请求之间传递数据,特别适用于存储持久性信息,如用户登录状态。我们演示了如何在Servlet中使用Cookie,包括设置Cookie和检索Cookie的值。

另一方面,Session对象是服务器端的会话管理机制,用于在服务器上存储用户会话数据,更适合存储敏感信息和临时数据。我们讨论了如何创建和操作Session对象,并比较了Session对象与request作用域的区别。

相关推荐
安之若素^8 分钟前
启用不安全的HTTP方法
java·开发语言
ruanjiananquan9915 分钟前
c,c++语言的栈内存、堆内存及任意读写内存
java·c语言·c++
chuanauc42 分钟前
Kubernets K8s 学习
java·学习·kubernetes
一头生产的驴1 小时前
java整合itext pdf实现自定义PDF文件格式导出
java·spring boot·pdf·itextpdf
YuTaoShao1 小时前
【LeetCode 热题 100】73. 矩阵置零——(解法二)空间复杂度 O(1)
java·算法·leetcode·矩阵
zzywxc7871 小时前
AI 正在深度重构软件开发的底层逻辑和全生命周期,从技术演进、流程重构和未来趋势三个维度进行系统性分析
java·大数据·开发语言·人工智能·spring
YuTaoShao3 小时前
【LeetCode 热题 100】56. 合并区间——排序+遍历
java·算法·leetcode·职场和发展
程序员张33 小时前
SpringBoot计时一次请求耗时
java·spring boot·后端
llwszx6 小时前
深入理解Java锁原理(一):偏向锁的设计原理与性能优化
java·spring··偏向锁
云泽野7 小时前
【Java|集合类】list遍历的6种方式
java·python·list