【Servlet篇4】cookie和session
在这一篇文章当中,我们提到了什么是cookie和session。
【网络原理8】HTTP请求篇_革凡成圣211的博客-CSDN博客HTTP的常见属性,URL,User-Agent,Refer,get 和post的区别https://blog.csdn.net/weixin_56738054/article/details/129180661?spm=1001.2014.3001.5502它们分别是客户端会话技术和服务端会话技术。
分别把用户的信息保存在客户端磁盘和服务端,二者一般是相互配合使用的。
当用户访问一个网站之后,这个网站会把用户的关键信息(例如身份标识符)存储到cookie当中,也就是用户的本地磁盘当中。
当后续用户再次访问这个网站的时候,就会携带这个cookie,然后在服务器当中根据这个cookie来获取这个用户的其他信息。
下面,就来聊一下session和cookie的常见api
目录
HttpSession session=req.getSession();
当传入参数为true的时候:
当传入参数为false的时候:
当调用getSession()方法的时候,会做什么事情
步骤1:创建会话
步骤2:获取会话
HttpSession对象
setAttribute()和getAttribute()
Cookie[] getCookies方法
resp.addCookie()方法
实现登录-跳转页面的案例
第一步:约定登录前后端交互的格式
登录接口的请求方式:
登录接口的响应方式:
第二步:约定如何获取主页的交互
获取主页的请求方式:
响应的格式:
第三步:编写登录的接口,并且把用户登录的信息保存在session当中
第四步:编写访问index页面的servlet
实现一个用户访问页面的次数的功能
如果在其中一个浏览器登录了,可以在另外一个浏览器直接访问登录页面吗?
HttpSession session=req.getSession();
这一个方法,既可以用于获取到服务器上面的会话,又可以用于创建会话。
但是,这一个方法在HttpServletRequest当中是存在多态的。
当传入参数为true的时候:
会话存在,则获取;会话不存在,则创建。
当传入参数为false的时候:
会话存在,则获取;会话不存在,则返回null
当调用getSession()方法的时候,会做什么事情
步骤1:创建会话
首先先获取到HTTP请求头当中cookie这个属性里面的sessionId字段。
接着,判断这一个sessionId是否在当前的服务器当中存在。
如果不存在,那么就进入创建会话的逻辑。
第一步:首先创建一个HttpSession对象,并且生成一个sessionId(用16进制来表示);
第二步:把sessionId作为key,这一个session对象作为value。保存到服务器的一个类似于"哈希表"的结构当中。(这个数据是保存到内存当中的,并不是持久化的)
第三步:服务器返回一个HTTP响应,把sessionId通过Set-cookie字段返回给浏览器。
也就是返回给用户。
然后用户下次再次访问的时候,就可以通过这个cookie字段来获取了。
下面,图解一下创建会话的流程:
步骤2:获取会话
先获取到请求的cookie里面的sessionId字段。
然后判断这个sessionId是否在当前的服务器上面存在(也就是是否在这个哈希表当中存在)
如果有,那么直接返回这个sessionId对应的对象。
HttpSession对象
每一个HttpSession对象都是通过键值对的形式来存储数据的。
当存储数据的时候,需要调用session.setAttribute(k,v)的方式来存储。
key是String的类型,value是Object的类型
看上去有点绕,怎么出现了套娃呢...那就画个图来解释一下吧~:
一个服务器当中可以有多个session对象,每一个session对象都拥有一个sessionId。
每一个session对象都对应多个键值对
setAttribute()和getAttribute()
这两个方法,左边的那个是拥有设置key-value的。右边那个是通过key来获取value的。
当调用setAttribute之后,就相当于往已经创建的session对象当中存放key和value。
Cookie[] getCookies方法
通过调用req.getCookies方法,可以获取到用户提交的HTTP请求头当中的cookie字段对应哪些键值对:代码实现
@WebServlet("/servlet4")
public class Servlet4 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {Cookie[] cookies= req.getCookies();for(int i=0;i<cookies.length;i++){Cookie cookie=cookies[i];System.out.println(cookie.getName()+"...."+cookie.getValue());}}
}
运行结果:
使用Fidller抓包:
可以看到,此时服务器就获取到了两个cookie对象。
resp.addCookie()方法
此处传入的是一个Cookie类型的数据,Cookie也是由键值对组成的结构。键和值都是String类型的数据。
Cookie cookie=new Cookie("hello","hi");
Cookie cookie1=new Cookie("hello","hi");
resp.addCookie(cookie);
resp.addCookie(cookie1);
这个addCookie方法,其实就相当于给客户端浏览器发送一个cookie类型的键值对。
然后,可以在HTTP响应报头的set-cookie字段当中看到这一个字段。
下面,通过一个网页登录的案例来体会一下cookie和session。
实现登录-跳转页面的案例
第一步:约定登录前后端交互的格式
登录接口的请求方式:
协议版本:HTTP/1.1
请求方法:POST;
请求路径:/Servlet;
接收方式(Content-type):application/x-www.form-urlencoded
(也就是userName="***"&password="***")这样的格式
登录接口的响应方式:
响应行:HTTP/1.1 302(需要重定向);
重定向:Location: index。(重定向到index这个路径)
第二步:约定如何获取主页的交互
获取主页的请求方式:
HTTP版本:HTTP/1.1
请求方法:GET;
请求路径:/index;
没有参数需要提交
响应的格式:
HTTP版本:1.1;
状态码:200;
响应格式:Content-Type: text/html(返回一个html页面)
第三步:编写登录的接口,并且把用户登录的信息保存在session当中
登录的时候,通过req.getSession()来创建一个session对象。
并且把userName存放到session域当中。
约定需要跳转的路径(/index)
@WebServlet("/login")
public class Servlet5 extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf-8");//处理用户请求String userName=req.getParameter("userName");String password=req.getParameter("password");//此处简单模拟一下登录成功的情况if("张三".equals(userName)&& "123".equals(password)){//往会话当中存储键值对:用于保存用户登录的信息//此处指定的参数为true,那么:需要此时会创建一个sesion对象HttpSession session=req.getSession(true);//把用户名存入session当中,代表用户已经登录成功了session.setAttribute("userName",userName);resp.sendRedirect("index");}else{//登录失败resp.getWriter().write("login faild");}}
}
第四步:编写访问index页面的servlet
再次调用req.getSession方法,但是此处需要指定参数为false
因为此处的session就是为了验证用户登录与否,无需再次创建新的会话。
此处的session对象和第三步当中的session期待是同一个session对象。
因为期待是同一个会话。
@WebServlet("/index")
public class IndexServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取到用户名//此处getSession参数为false,原因:此处已经创建过会话了HttpSession session =req.getSession(false);resp.setCharacterEncoding("utf-8");//根据key来获取valueString userName= (String) session.getAttribute("userName");//返回一个主页resp.getWriter().write("<h3>欢迎你!"+userName);}
}
实现一个用户访问页面的次数的功能
无需太大的改动。只需在用户登录的时候,设置一个count统计用户登录的次数。这一个count需要使用session保存。
然后在页面(index)处,每一次用户取出来数据,都要+1。
代码实现:
登录页面
@WebServlet("/login")
public class Servlet5 extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf-8");//处理用户请求String userName=req.getParameter("userName");String password=req.getParameter("password");//此处简单模拟一下登录成功的情况System.out.println(userName+"..."+password);if("张三".equals(userName)&& "123".equals(password)){//往会话当中存储键值对:用于保存用户登录的信息//此处指定的参数为true,那么:需要此时会创建一个sesion对象HttpSession session=req.getSession(true);//把用户名存入session当中,代表用户已经登录成功了session.setAttribute("userName",userName);//登录成功,默认初始的值为0session.setAttribute("count",0);resp.sendRedirect("index");}else{//登录失败resp.getWriter().write("login faild");}}
}
index页面
@WebServlet("/index")
public class IndexServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取到用户名//此处getSession参数为false,原因:此处已经创建过会话了HttpSession session =req.getSession(false);//根据key来获取valueString userName= (String) session.getAttribute("userName");resp.setCharacterEncoding("utf-8");//获取一个count的值Integer count= (Integer) session.getAttribute("count");Integer newCount=count+1;//在session当中保存自增过后的countsession.setAttribute("count",newCount);//返回一个主页resp.getWriter().write("<h3>欢迎你!"+userName+"您访问此页面的次数为:"+newCount);}
}
如果在其中一个浏览器登录了,可以在另外一个浏览器直接访问登录页面吗?
不行的。来做个实验看一下:
首先,启动Tomcat,默认在360安全浏览器打开页面。
然后登录(登录的接口跟上面的是一样的,都是/login),同时使用Fidler抓包
然后,再抓一下访问index页面的URL的包:
换一个浏览器,再次访问index页面的URL
可以看到,换了一个浏览器,因为cookie当中包含的sessionID不一样了,也就没有办法保存原来sessionid当中的值,那么就无法获取到在原来的浏览器保存的session信息了。
(每一个浏览器都会有自己的cookie,也就意味着不同的浏览器有不同的sessionId)
总结:cookie和session的区别
使用对象 | 数据类型 | 安全性 | 存储大小 | 存储位置 | |
cookie | 针对网站: 每一个网站都会被分配一组cookie | (String,String) | 比较低,容易丢失、篡改 | 较小;一个cookie不超过3K | 保存在客户端浏览器(磁盘) |
session | 针对用户: 只有客户端才可以访问。 程序为客户端添加一个sessionId. 每一个sessionId对应一个HttpSession对象 | (String,Object) | 比较高 | 可以存储任意大的数据 | 保存在服务端 |
相关文章:

【Servlet篇4】cookie和session
在这一篇文章当中,我们提到了什么是cookie和session。 【网络原理8】HTTP请求篇_革凡成圣211的博客-CSDN博客HTTP的常见属性,URL,User-Agent,Refer,get 和post的区别https://blog.csdn.net/weixin_56738054/article/details/1291…...

考研流程,可以进来转一转(考研你不知道的事情)(详细版)
之前有听过好多人说要考研,那么,考研的信息,如何获取呢,考研都有哪些流程呢。 初试开始到考试:↓ 1、了解考研信息。 2、确定自己要报考的专业。(本专业or跨考) 3、选择地区 4、选择要报考的学…...

3.2 LED闪烁流水灯蜂鸣器
LED闪烁1.1 电路连接示意图LED采用低电平点亮的方式,利用ST-Link的3.3V进行供电。1.2程序设计1.21知识储备GPIO配置步骤步骤:1. 第⼀步,使⽤RCC开启GPIO的时钟2. 第⼆步,使⽤GPIO_Init()函数初始化GPIO3. 第三步,使⽤输…...

刷题笔记3 | 203. 移除链表元素、707设计链表,206.反转链表
目录 203. 移除链表元素 707、设计链表 206.反转链表 203. 移除链表元素 题意:删除链表中等于给定值 val 的所有节点。 示例 1: 输入:head [1,2,6,3,4,5,6], val 6 输出:[1,2,3,4,5] 示例 2: 输入:h…...

[一篇读懂]C语言十一讲:单链表的删除和单链表真题实战
[一篇读懂]C语言十一讲:单链表的删除和单链表真题实战1. 与408关联解析及本节内容介绍1 本节内容介绍2. 单链表的删除操作实战3. 单链表真题解读与解题设计1 题目解读2 解题设计第一阶段:双指针找中间结点第二阶段:原地逆置第三阶段ÿ…...

【C++初阶】list的使用
大家好我是沐曦希💕 文章目录一、前言二、构造三、迭代器四、增删查改1.头插头删2.尾插尾删3.查找和插入4.删除五、其他成员函数1.排序和去重2.splice和remove3.resize一、前言 list本质是带头双向循环链表,本文只对list的一些常用接口进行说明…...

HTML 布局
网页布局对改善网站的外观非常重要。 请慎重设计您的网页布局。 在线实例 使用 <div> 元素的网页布局 如何使用 <div> 元素添加布局。 使用 <table> 元素的网页布局 如何使用 <table> 元素添加布局。 网站布局 大多数网站会把内容安排到多个列中&a…...

如何在虚拟机中安装ikuai软路由系统
首先访问ikuai官网下载固件固件下载-爱快 iKuai-商业场景网络解决方案提供商 (ikuai8.com) 根据需求下载 然后创建一个虚拟机,点击下一步 选择更下载的ISO映像文件,点击下一步 点击下一步 设置一下名称和储存位置,点击下一步 根据需求设置&a…...

Java 多线程 --- 线程协作 wait/notify
Java 多线程 --- 线程协作 wait/notifywait / notifyObject.wait() , Object.notify() / notifyAll()notify 和 wait 的原理notify会导致死锁的问题wait / notify的开销以及问题wait / notify 在多线程中, 如果程序拿到锁之后, 但是没有满足指定条件而不能继续往下执行, 我们可…...

【PyTorch】教程:torch.nn.Hardsigmoid
torch.nn.Hardsigmoid 原型 CLASS torch.nn.Hardsigmoid(inplaceFalse) 参数 inplace (bool) – 默认为 False 定义 Hardsigmoid(x){0if x≤−3,1if x≥3,x/61/2otherwise\text{Hardsigmoid}(x) \begin{cases} 0 & \text{if~} x \le -3, \\ 1 & \text{if~} x \ge 3…...

【手把手一起学习】(八) Altium Designer 20修改和自定义原理图标题栏
1 修改原理图标题栏 直接对原理图标题栏属性进行修改,操作如图所示: 修改后,并不会显示,故该方法不可用: 正确的操作如下,先选择合适的模板: 然后,进行属性的修改: 此时…...
业务流程测试
用例设计主要问题主要问题存在于:1、测试点分析:逻辑性不强对于整个页面功能划分不清晰;不同测试点归类不清晰;不能形成相对固定的套路,书写耗费大量时间...2、测试用例:关于,要细致到什么程度&…...

[极客大挑战 2019]EasySQL 1
[极客大挑战 2019]EasySQL 1解题POC一、解题思路之暴力破解1. 弱口令2. 暴力破解二、解题思路之万能密码1. 什么是万能密码2. 测试过程解题POC 直接点击登录获取flagflag{62f0d2ca-579e-450e-941f-5f7c23a8baf7} 一、解题思路之暴力破解 这题是万能密码,所以暴力破解…...

vulnhub raven2复现
1.扫描全网段,找出了存活主机ip为192.168.85.144 nmap 192.168.85.0/24 2.nmap扫描端口 nmap -p1-65535 192.168.85.144 3.访问此网站,没找到什么地方可以利用漏洞 ,查看中间件为wordpress 4.使用dirb对该网站进行目录扫描 dirb http://1…...
LeetCode 剑指 Offer II 079. 所有子集
给定一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1: 输入:nums [1,2,3] 输出:[[],[1],[2],[1,2],[3…...

打印名片-课后程序(Python程序开发案例教程-黑马程序员编著-第二章-课后作业)
实例3:文本进度条 进度条以动态方式实时显示计算机处理任务时的进度,它一般由已完成任务量与剩余未完成任务量的大小组成。本实例要求编写程序,实现图1所示的进度条动态显示的效果。 下载中下载完成图1文本进度条 实例分析 在本实例中可以将…...
为什么我们在判断字符串不为null后还要判断字符串长度大于0?
我们在做字符串判断时一般会: if (s ! null && s.length() > 0) {} 但是我就在想,字符串不为空了,那么他一定有值,字符串长度不就大于0吗,所以s.length()>0是不是有点多余? 我的思维误区是…...

javaEE 初阶 — 应用层中的 DNS 协议(域名解析系统)
文章目录什么是域名1. 如何建立 域名 与 IP 的对应关系2. 域名的分级什么是域名 域名也就是平常所说的网址,比如 www.baidu.com。 其实网络上的服务器要访问这个网址,需要的是 IP 地址。、 但是 IP 地址比较拗口不方便记忆,于是就有使用一些…...

【网络】-- 网络编程套接字(铺垫、预备)
目录 理解源IP地址和目的IP地址 认识端口号 端口号 理解源端口号和目的端口号 套接字 认识TCP与UDP协议 网络字节序 socket编程接口 socket 常见API sockaddr结构 理解源IP地址和目的IP地址 就如同我们唐僧的取经路: 唐僧的出发地到目的地:东…...
一文打通@SentinelResource
Sentinel 提供了 SentinelResource 注解用于定义资源,并提供了 AspectJ 的扩展用于自动定义资源、处理 BlockException 等 如果使用的是Sentinel Annotation AspectJ Extension,需要导这个依赖 <dependency><groupId>com.alibaba.csp</…...

智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...
前端高频面试题2:浏览器/计算机网络
本专栏相关链接 前端高频面试题1:HTML/CSS 前端高频面试题2:浏览器/计算机网络 前端高频面试题3:JavaScript 1.什么是强缓存、协商缓存? 强缓存: 当浏览器请求资源时,首先检查本地缓存是否命中。如果命…...

热门Chrome扩展程序存在明文传输风险,用户隐私安全受威胁
赛门铁克威胁猎手团队最新报告披露,数款拥有数百万活跃用户的Chrome扩展程序正在通过未加密的HTTP连接静默泄露用户敏感数据,严重威胁用户隐私安全。 知名扩展程序存在明文传输风险 尽管宣称提供安全浏览、数据分析或便捷界面等功能,但SEMR…...
Python学习(8) ----- Python的类与对象
Python 中的类(Class)与对象(Object)是面向对象编程(OOP)的核心。我们可以通过“类是模板,对象是实例”来理解它们的关系。 🧱 一句话理解: 类就像“图纸”,对…...

dvwa11——XSS(Reflected)
LOW 分析源码:无过滤 和上一关一样,这一关在输入框内输入,成功回显 <script>alert(relee);</script> MEDIUM 分析源码,是把<script>替换成了空格,但没有禁用大写 改大写即可,注意函数…...