【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</…...

苹果手机备份的文件在电脑什么地方 苹果备份文件怎么查看
在这个网络信息时代,为手机进行定期备份已经成为了家常便饭。在使用备份软件对苹果手机进行备份后,苹果手机备份的文件在什么地方,苹果备份文件怎么查看呢?本文就带大家来了解一下。 一、苹果手机备份的文件在电脑什么地方 大家…...

【MySQL速通篇001】5000字超详细介绍MySQL部分重要知识点
🍀 写在前面 这篇5000多字博客也花了我几天的时间😂,主要是我对MySQL一部分重要知识点的理解【后面当然还会写博客补充噻,欢迎关注我哟】,当然这篇文章可能也会有不恰当的地方【毕竟也写了这么多字,错别字可…...

并发编程——synchronized优化原理
如果有兴趣了解更多相关内容,欢迎来我的个人网站看看:耶瞳空间 一:基本概念 使用synchronized实现线程同步,即加锁,实现的是悲观锁。加锁可以使一段代码在同一时间只有一个线程可以访问,在增加安全性的同…...

LeetCode 剑指 Offer II 083. 没有重复元素集合的全排列
给定一个不含重复数字的整数数组 nums ,返回其 所有可能的全排列 。可以 按任意顺序 返回答案。 示例 1: 输入:nums [1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] 1 < nums.length < 6 -10 < nu…...

JSONObject与JSONArray使用区别
目录 1.使用的场景区别 2. 使用方法区别 3.获取方式不同 4. 解析JSON字符串 5.总结 1.使用的场景区别 想通过键值对的形式获取数据,使用JSONObject。如果后台查询的是某个bean的list集合向前端页面传递,使用JSONArray。 2. 使用方法区别 创建方法不…...

经典C程序例程:通过进程ID得到文件名
通过进程ID得到文件名 #include <stdio.h> #include <windows.h> #include <tlhelp32.h> #include <tchar.h>BOOL EnablePrivilege(HANDLE hToken,LPCSTR szPrivName); void DispProcess(void); void DispPrsFile(void);// typedef BOOL (_stdcall *E…...

【Java】Spring MVC程序开发
文章目录Spring MVC程序开发1. 什么是Spring MVC?1.1 MVC定义1.2 MVC 和 Spring MVC 的关系2. 为什么学习Spring MVC?3. 怎么学习Spring MVC?3.1 Spring MVC的创建和连接3.1.1 创建Spring MVC项目3.1.2 RequestMapping 注解介绍3.1.3 Request…...

leetcode题解-704. 二分查找
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。 示例 1: 输入: nums [-1,0,3,5,9,12], target 9 输出: 4 解释: 9 出现…...

2.2 C语言程序的错误条件
在C语言程序中,条件语句决定程序的执行路径,因此条件表达式是程序的关键。 应用最经典的程序,除法的减法实现程序,解释条件表达式的重要性。x=y*q+r,x是被除数,y是除数,q是商,r是余数。 程序的方法, x=(r-y)+y*(1+q)。 main(){ /*错误条件的程序*/ r:=x; q:=0; whil…...

laravel 邮件发送
配置 Laravel 的邮件服务可以通过 config/mail.php 配置文件进行配置。 邮件中的每一项都在配置文件中有单独的配置项,甚至是独有的「传输方式」,允许你的应用使用不同的邮件服务发送邮件 mailers > [smtp > [transport > smtp,host > env(M…...