“会话技术”——Cookie_(2/2)原理与使用细节

经过Cookie的快速入门与代码使用。如果想深入理解Cookie的技术实现,就得去理解它的原理。
且有些时候使用Cookie,还要根据需求设置存活期限以及确定Cookie获取范围等其他细节。最后,我们会总结Cookie这门客户端会话技术的作用。


一、原理

注:我们还是使用简易图画进行辅助理解

注:这是上一节写的代码(两个Servlet),这里将这个例子使用一下分析Cookie的原理

所谓分析Cookie原理,正是分析: 服务器端如何响应时发送Cookie,以至于浏览器端识别了还自动保存;并且CookieDemo2怎么获取到的Cookie,即浏览器怎么就携带了Cookie信息进行了下一次请求。

1.1 分析:

 其实不管发送数据也好,还是获取数据(站在服务器端看)也好,它们在客户端与我端(服务端)中间都是以HTTP协议进行交互——响应和请求一定是遵循HTTP协议的

首先,客户端发送了第一次请求,请求访问了服务器端的资源——CookieDemo1。

CookieDemo1收到了请求,于是以“发送Cookie”进行处理数据并响应了(确实向浏览器发送了Cookie),刚刚说“所有的客户与服务器端的响应请求都遵循HTTP协议”。所以那实际上,“发送Cookie”时,怎么发送呢? 服务器(response端)会在响应报文中设置一个名为“Set-Cookie”的响应头,该响应头的值以键值对的形式呈现,恰好可用于存储Cookie

于是浏览器端会收到来自服务器端的响应报文,发现响应报文的响应头有“set-Cookie”。浏览器因为熟读HTTP协议,所以遵循协议:如果浏览器收到了set-Cookie响应头,它应该将这个头里携带的数据(“name=Bear”)保存到自己本地中。

而在第二次请求时,HTTP协议又规定了:浏览器应该在下一次请求中将保存的数据(“name=Bear”)放进一个Cookie的请求头中(作为值)。浏览器端会在请求报文中设置一个Cookie请求头,其值类型也为键值对,恰好也用来放Cookie数据。

 于是CookieDemo2能从请求头中获取到Cookie信息。但是,在咱们使用Cookie代码获取请求里的Cookie,并不是操作所谓的“Cookie这个请求头”,而是怎么? 

Cookie[] cookies = request.getCookies();
//这样一个名叫getCookies()的方法

 这也得多亏了JAVA EE 内部实现的API,封装的库方法(函数)。让我们调用里的方法就能发送和获取Cookie,而方法便是去和请求头或者响应头打交道,我们放心调用就行。

1.2 看看:

初见"set-Cookie"响应头和“Cookie”请求头,不熟悉很正常,多看几眼。我们在浏览器抓包

1.2.1抓包

(浏览器端)按F12键 ,接着如图操作:

我们现在运行,访问CookieDemo1—— :抓抓它的响应包: 

是吧,这发送Cookie响应时会真的有一个响应标头Set-Cookie。

那如果我们继续请求CookieDemo2:抓抓它的请求报文,是不是在存储Cookie后下一次请求就会在请求头里捎带上Cookie数据。

确实是。 

 二、Cookie的细节

2.1 一次可不可以发送多个cookie呢?

了解了原理这个问题== 响应报文set-Cookie的值可以是多个键值对吗? 

我们修改修改CookieDemo1:

// 原
@WebServlet("/CookieServlet01")
public class CookieServlet01 extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{// 1. 创建Cookie,绑定数据Cookie cookie = new Cookie("name","Bear");// 2. 发送Cookie对象response.addCookie(cookie);}}

我们再创建一个Cookie,让response调用两次addCookie();

protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{// 1. 创建Cookie,绑定数据Cookie cookie = new Cookie("name","Bear");Cookie cookie2 = new Cookie("place","Toilet");//新建// 2. 发送Cookie对象response.addCookie(cookie);response.addCookie(cookie2);//连着发送}

运行这段代码,即重新请求CookieDemo1,抓抓它的请求包:

答案:一次可以发送多个Cookie。

为了完整,我们再访问打印Cookie的那个Servlet,抓抓这回的请求包:

都存了,是的,刚刚响应发来的Cookie都存进浏览器了;这会儿,也全部放进请求头Cookie了。

2.2 Cookie在浏览器中能保存多长时间?

默认情况下,当浏览器关闭后,Cookie数据被销毁;因为默认存到浏览器内存里,程序结束,内存就会删除数据。

如果想设置持久化存储,我们这里再学习一个Cookie的方法:

cookie.setMaxAge(int seconds)
//参数是int类型,单位为秒数。
// int 是有符号整型,于是根据取值的不同,该方法会实现不同的效果

 若seconds 为 正数 :意味着 a. 将Cookie数据写到硬盘的文件中、持久化存储。

b. 规定了该Cookie存活的时间

若seconds 为 0 : 意味着删除该Cookie。设置完cookie的MaxAge,需要将这个Cookie发送给客户端。

为什么秒数为0,就意味着删除? 这句话看似只有1个问,其实有2个答案。
1. Cookie 最大存活期限为0,那么就意味着“不存在”。
2. Cookie是存在用户端的数据,服务器端不能直接操作客户端的数据,所以服务器想要删除Cookie就用这种方式:设MaxAge=0,再响应发送。

若seconds为 负数:意味着默认设置(所以设为负数,跟不设置MaxAge效果一样:一旦关闭浏览器,存在内存里的Cookie就会被释放,失效)

代码实践timing :

我们新建一个CookieServlet03来创建和发送Cookie。

/** CookieDemo03 用来创建和发送Cookie* 分别设置存活期限:*  ^ 正数*  ^ 负数*  ^ 0* */
@WebServlet("/CookieServlet03")
public class CookieServlet03 extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{// 1. 创建Cookie,绑定数据// 2. 设置Cookie的存活期限// 3. 发送Cookie对象}
}

 写入核心代码:

        // 1. 创建Cookie,绑定数据Cookie cookie = new Cookie("name","bear");// 2. 设置Cookie的存活期限cookie.setMaxAge(30);//设置正数的存活期限,代表了:1.将Cookie数据写到硬盘的文件中。持久化存储。2.Cookie存活时间// 3. 发送Cookie对象response.addCookie(cookie);

 验证逻辑:我们重新打开浏览器,先访问CookieServlet03(客户端收到cookie会存起来),再请求访问CookieDemo02(这时可在Eclipse控制台打印出Cookie信息)。

如果在30秒之内,我们关闭浏览器又访问CookieServlet02,按理可以获取并打印这个Cookie:

如果超过30秒后,我们再次访问CookieServlet02,我们再看控制台:

负数和0的取值,也是同样验证步骤。

 2.3 cookie能不能存中文?

在tomcat 8之前,不能存中文。

那怎么办? 需要将中文数据转码 —— 一般采用URL编码(如:%E3)

在tomcat 8之后 ,cookie支持中文数据,但还是不支持特殊字符。

我们现在使用的是tomcat 9,故tomcat8之前的不做演示。

运行服务器,访问CookieServlet03,再访问CookieServlet02打印:

以上验证,tomcat8以上,Cookie能存中文。

2.4 cookie获取范围多大?

假设在一个服务器(也就是一个tomcat)中,部署了多个web项目,那么在这些web项目中cookie能不能共享?

图:工程目录下的项目们

经过作者的超绝不经意安排,有以下两个项目: 

 它们的cookieDemo2和cookieServlet02都是获取request的Cookies并打印。

这时我们验证的问题:项目1下的cookieServlet01发送给客户端的Cookie,会被项目2下的cookieDemo2获取到吗(即跨项目的cookie能获得吗)

项目1下的CookieServlet01

我们接下来就访问这个Servlet:

接着我们访问项目2下的cookieDemo2: 

 最后得到验证:

假设在一个服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?
默认情况下cookie不能共享

假如就有这个需求,需要一个服务器上多个项目共享Cookie,该如何呢?

2.4.2 多个项目共享Cookie

之所以Cookie多个项目不能共享,是因为默认情况下,客户端存储的Cookie目录是以项目名为目录的:

项目不同,项目名就不同。自然该目录下就不会出现其他项目名的Cookie。

这里引入Cookie的另一个方法:

Cookie.setPath(String Path);
//参数为字符串类型,表示该cookie的存储路径。

 运行:

 此时若我们再访问另一个项目下的打印Servlet:

 

再看控制台,成功打印了项目1刚刚存的Cookie。

所以,想要实现一个服务器下多个项目下的Cookie共享:就setPath()。

2.4.3 多个服务器Cookie共享

其实还是同样的道理,调用cookie方法,但是是不同的方法:

setDomain(String path)
// 参数:字符串类型,设置域名

如果设置一级域名相同,那么多个服务器之间的cookie可以共享
如果SetDomain(“.baidu.com”),那么tieba.baidu.com和news.baidu.com中cookie可以共享
因为这两个服务器都是baidu管辖下的,那何必要设置两个服务器呢?是因为如果一个服务器承受不了大量的用户请求访问。

比较浅显的解释,但这里简单提出,仅为知识体系的完整。后面再次接触的时候就会深入应用。

三、Cookie的特点和作用:

特点:

1.    cookie存储数据在客户端浏览器
2.    浏览器对于单个cookie的大小有限制(4kb左右) 以及 对于同一个域名下的总cookie数量也有限制(20个)
这Cookie的名字也暗示了存不了多少数据。Cookie——“小甜点”,饭后甜食或者下午茶小点心,不能当主食。

 作用:

1.    Cookie一般用于存储少量的不太敏感的数据
2.    在不登录的情况下,完成服务器对客户端的身份识别;而登录的话,就是在数据库里获取数据

“不太敏感”,存在客户端,咱们一抓包或者在“开发者工具”里就能看到,服务器这边还能删除……无不昭示着客户端安全性不太高,尽量不存敏感数据。

 第二点还挺重要,需要好好理解:

我们来到baidu的主页面:

我们在输入框输入问题:

 如果我们既不登录,又想实现输入问题的时候没有自动联想:

我们再次来到主页面,此时还是未登录状态:

若我关闭浏览器,再次进入baidu,输入问题也没有自动联想。为什么呢?是因为刚刚的“保存设置”时发出请求,baidu响应了这些设置,数据以set-Cookie标头响应过来。

浏览器保存这些信息(Cookie),而我们再次来到baidu主页面:我们的请求会自动携带Cookie。而baidu服务器则会获取请求里的Cookie,再将我们的需求响应给我们。

这就是Cookie:在未登录的状态下 ,服务器完成对客户端身份的识别。如果登录的话,服务器就直接在它的数据库里提取数据了。


下一节:Cookie的实战应用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/81446.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DBeaver连接人大金仓数据库V9

1、官网下载驱动jdbc 打开官网地址,找到下面的V9R1-JDBC,点击后面的下载即可,保存到本地 2、解压最新版的驱动程序 3、把***_JDBC文件夹内的驱动程序复制到DBeaver安装目录下的plugins文件夹里 4、打开dbeaver程序,增加kingbase…

服务器丢包率测试保姆级教程:从Ping到网络打流仪实战

测试服务器丢包率是网络性能诊断的重要环节,丢包通常由网络拥塞、硬件故障、配置错误或线路质量差导致。以下是多种测试方法的详细步骤和工具说明: 一、基础工具测试(无需专业设备) 1. 使用 ping 命令 命令示例: bash…

n8n 使用 AI Agent 和 MCP 社区节点

n8n 使用 AI Agent 和 MCP 社区节点 0. 前提条件1. 创建一个 "在聊天消息时" 节点2. 创建一个 "AI Agent" 节点 0. 前提条件 请参考 n8n 安装 n8n-nodes-mcp 社区节点 安装 MCP 社区节点。 1. 创建一个 “在聊天消息时” 节点 单击 “测试聊天”&#xf…

抱佛脚之学SSMSpringMVC数据绑定

绑定默认数据类型 绑定简单数据类型 绑定POJO类型 绑定包装POJO 复杂数据绑定 绑定数组 绑定集合

解决“‘mvn‘ 不是内部或外部命令,也不是可运行的程序”错误

一、问题描述 当我们在Windows上运行sqlrest 工具时,提示mvn 不是内部或外部命令,也不是可运行的程序的错误,导致无法安装sqlrest工具,如下图所示: 二、问题分析 从提示中我们不难看出是由于我们缺失了【maven】环境,导致无法启动项目;我们只需要安装【maven】环境即可解…

DeepSeek R1:强化学习范式的推理强化模型

定位与目标 DeepSeek R1 的推出并非 DeepSeek V3 的简单迭代,而是一次在训练范式上的大胆探索。与传统大模型主要依靠监督微调(SFT)后进行强化学习不同,R1 将重点放在推理能力和行为对齐上,尝试通过大规模强化学习直接激发模型的推理潜力。其目标是利用强化学习的反馈机制,…

变转速振动信号分析处理与故障诊断算法模块

变转速振动信号分析处理与故障诊断算法模块,作为信号处理算法工具箱的主要功能模块,形成了以变转速振动信号分析处理与故障诊断算法模块的经典算法模型,可应用于各类关键机械部件(轴承、齿轮、转子等)的信号分析、故障…

Kafka 配置参数性能调优建议

文章目录 1、生产者调优batch.size(重要)linger.mscompression.typeacks(重要)buffer.memorymax.in.flight.requests.per.connection(重要)message.max.bytes(重要) 2、消费者调优fe…

Redis怎么避免热点数据问题

使用 RedisTemplate 避免热点数据问题的解决方案、场景及示例: 1. 数据分片(Sharding) 场景:高频读写的计数器(如文章阅读量统计) ​原理​:将数据分散到多个子键,降低单个 Key 的压…

B站Michale_ee——ESP32_IDF SDK——FreeRTOS_8 消息缓冲区

Message Buffer(消息缓冲区)与Stream Buffer(流数据缓冲区)类似,但有2点不同: Message Buffer每次只接收1次完整的Message;Message Buffer接收缓冲区小于1条Message大小时,会接收不到数据&#…

【计算机网络网络层深度解析】从IP协议到路由优化

目录 前言技术背景与价值当前技术痛点解决方案概述目标读者说明 一、技术原理剖析核心概念图解核心作用讲解关键技术模块说明技术选型对比 二、实战演示环境配置要求核心实验实现实验1:IPv6地址配置实验2:OSPF路由配置实验3:NAT转换验证 运行…

【Hive入门】Hive性能调优:小文件问题与动态分区合并策略详解

目录 引言 1 Hive小文件问题概述 1.1 什么是小文件问题 1.2 小文件产生的原因 2 Hive小文件合并机制 2.1 hive.merge.smallfiles参数详解 2.2 小文件合并流程 2.3 合并策略选择 3 动态分区与小文件问题 3.1 动态分区原理 3.2 动态分区合并策略 3.3 动态分区合并流程…

如何让Steam下载速度解除封印?!

平时一直没注意到家里的路由器在偷懒。最近成功榨干家里的带宽,把平时一直20mb/s左右下载速度的路由器一番改造后成功steam下载速度稳定85Mb/s。平时一直都只发挥了他的1/3不到,真是太可惜了。 硬件 首先检查硬件,就千兆路由器而言&#xf…

通信原理第七版与第六版的区别附pdf

介绍 我用夸克网盘分享了「通信原理 第7版》樊昌信」, 链接:https://pan.quark.cn/s/be7c5af4cdce 《通信原理(第7版)》是在第6版的基础上,为了适应当前通信技术发展和教学需求,并吸取了数十所院校教师的反…

【2025五一数学建模竞赛A题】 支路车流量推测问题|建模过程+完整代码论文全解全析

你是否在寻找数学建模比赛的突破点?数学建模进阶思路! 作为经验丰富的美赛O奖、国赛国一的数学建模团队,我们将为你带来本次数学建模竞赛的全面解析。这个解决方案包不仅包括完整的代码实现,还有详尽的建模过程和解析&#xff0c…

Python爬虫实战:获取彼岸网高清素材图片

一、引言 在数字化时代,图片素材的需求持续增长。彼岸网提供了丰富的高质量图片资源,其中 4K 风景图片备受用户青睐。借助 Python 爬虫技术,可自动化地从彼岸网获取这些图片,为用户提供便捷的图片素材服务。然而,爬取过程中会遭遇登录验证、反爬机制等问题,需采用相应技…

深入理解 C++ 数据类型:从基础到高级应用

C 是一种强类型语言,这意味着每个变量都必须有明确的数据类型,以便编译器知道如何存储和操作数据。数据类型决定了变量的内存占用、取值范围以及可以执行的操作。理解 C 的数据类型是编写高效、安全代码的基础。本文将全面介绍 C 的数据类型,…

补题:K - Magic Tree (Gym - 105231K)

来源:问题 - K - Codeforceshttps://codeforces.com/gym/105231/problem/K 题目描述: 一、题目分析 本题给定一个2行m列的网格,从(1, 1)格子开始进行深度优先搜索,每个格子可到达至少一个边相邻的格子且不重复访问,…

【Prometheus-OracleDB Exporter安装配置指南,开机自启】

目录 1. 安装Oracle Instant Client1.1 解压安装包1.2 创建运行时链接 2. 环境配置2.1 设置环境变量2.2 验证配置 3. 安装Oracle DB Exporter3.1 创建工作目录3.2 解压安装包3.3 添加执行权限 4. 数据库监控配置4.1 创建监控用户(切换到Oracle所属用户) …

溯因推理思维——AI与思维模型【92】

一、定义 溯因推理思维模型是一种从结果出发,通过分析、推测和验证,寻找导致该结果的可能原因的思维方式。它试图在已知的现象或结果基础上,逆向追溯可能的原因,构建合理的解释框架,以理解事物的本质和内在机制。 二、由来 溯因推理的思想可以追溯到古希腊哲学家亚里士…