Cookie和session工作流程详解

news2024/11/24 8:59:45

目录

cookie机制

session会话

理解会话机制

Servlet中对Cookie和Session提供的

HttpServletrequest类中的方法:

模拟实现登录功能

首先实现功能分为两个界面:

 (1)登录页面代码(前端代码)

   (2) 编写LoginServlet处理上述登录请求

登录http请求格式如下:

   LoginServlet代码:

   验证用户登录要做的几个步骤:

编写主页的Servlet(登录成功之后跳转到的页面)

   index页面需要做的几个步骤:

   登录功能运行效果:

session会话是否会持久化保存?


前言

    虽然大部分客户端的数据都是从服务器中请求的,但是还有一小部分数据为了减轻服务器的负担,这一部分数据可以在浏览器本地中进行数据存储,如果此时的数据需要本地存储,是否可以直接写入硬盘呢,答案是否定的,如果允许网站直接把数据写入硬盘,此时有一些恶意网站就可能攻击客户端,把硬盘上的数据弄丢。

    所以引入了cookie机制,这种机制是可以把数据写入一些特定的文件的。

    此时身份标识如何分配,以及用户的身份信息如何具体存储(是需要服务器支持的),所以就有了Session(会话机制),通过Cookie和Session的配合,来完成本地数据的存储。

cookie机制

    首先类比到医院看病的例子,如果去医院看病,此时就需要以下的步骤:

1. 到医院后先挂号,此时就得到了一张就诊卡,这个就诊卡就是Cookie,里边有一个令牌,就是session。
2. cookie中存储了这个令牌(你的身份标识)
3. 后续去各个科室检查,开药,先刷就诊卡,就诊卡存储的是医生开的药,需要检查的项目。
4.  注:这个就诊卡中,只是存储了身份标识,此时你需要检查的项目,开的药方,都是根据就诊卡中的这个标识存储在医院的数据库中的,这个令牌(session)只是存储了你的身份标识。

    cookie是浏览器在本地存储数据的一种机制。cookie中存储了用户表示用户身份的一些信息。

cookie从哪里来?cookie是从服务器来,携带的数据就是用户需要在浏览器中保存的本地的数据,在响应中会带有Set-Cookie字段,通过这个字段就把本地数据返回给客户端。
cookie到哪去?cookie先是从服务器中把需要本地存储的数据传给客户端,之后客户端访问浏览器时就把本地的所有cookie通过http请求带给服务器。
cookie的作用最典型的应用就是用cookie保存当前用户的登录状态。

session会话

     如上图所示;这个令牌就是在cookie中保存的,Cookie用于保存用户身份标识,这样的场景中,身份标识如何分配,以及身份标识信息具体时如何进行存储的,都是需要服务器支持的。

    Session(会话)就是服务器用来实现用户身份区分的一种机制,通常是和Cookie搭配使用。

1. 首先给当前用户分配一个sessionId,同时记录下当前用户的一些身份信息(可以是自定义的)

2. sessionId就会被返回到浏览器的Cookie中,后续浏览器访问服务器时,就会带着sessionId。

3. 此时服务器就可以通过这个sessionId识别当前用户的身份了。

理解会话机制

    服务器同一时刻收到的请求是很多的,同一时刻服务器需要处理不同客户端发来的不同的请求,此时服务器就需要清楚的区分每个请求是属于哪一个用户的,就需要服务器记录每个用户令牌以及用户信息的对应关系。

    Session会话本质就是一个“哈希表”,存储了一些键值对结构,key就是令牌的id,value就是用户信息(用户信息是自定义的,灵活设计的)

   注:Session会话中的key必须是String类型,value是Object类(value可以是任意类型)。

Servlet中对Cookie和Session提供的支持

HttpServletrequest类中的方法:

 getSession方法的使用:

    getSession()中有一个参数,是boolean类型的,

    1. 如果参数为false,getSession的行为是:

(1)读取cookie中的sessionId
(2)在服务器中根据sessionId来查询对应的session对象
(3)如果查到了直接返回这个session对象,如果没有查到则返回null

    2. 如果参数为true,getSession的行为是:

(1)读取请求中cookie中的sessionId
(2)在服务器中根据sessionId来查询对应的session对象
(3)如果查到了,直接返回这个session对象
(4)如果没有查到,就会创建一个session对象,同时生成一个sessionId,以sessionId为key,session对象为value,把这个键值对鵆到服务器中的一个hash表中,同时把sessionId以 Set-Cookie的方式返回给浏览器

    注:如果参数为true,此时允许创建session对象,如果参数为false,此时不允许创建session对象。

模拟实现登录功能

     首先实现功能分为两个界面:

1. 登录页(包含两个输入框,输入用户名密码,以及一个登录按钮)点击登录按钮,就会发出一个http请求,服务器处理这个请求时会验证用户名和密码,如果用户名和密码都正确,就会跳转到主页。
2. 主页(只会显示当前登录的用户的用户名)(欢迎xxx)  其中,登录页就是一个html页面,还需要写一个Servlet,实现登陆时候用户名的密码校验,最后需要写一个Servlet 来生成主页(点击登录之后,跳转到主页中)。

(1)登录页面代码(前端代码)

/* form会组织用户输入的用户名和密码这部分数据以键值对的形式提交给服务器,
   其中 key 就是 input 的 name 属性
   其中 value 就是input 的 用户输入的内容
   最终会构造一个post请求,在body 中以键值对(类似query string)的格式进行数据的组织
*/
<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>登录页面</title>
    </head>

    <body>
        <form action="login" method="post">
            <input type="text" name="username" id="">
            <input type="password" name="password" id="">
            <input type="submit" value="登录" name="" id="">
        </form>
    </body>

</html>

(2) 编写LoginServlet处理上述登录请求

    登录http请求格式如下:

POST /login(一般的登录请求都是post方法,就是向服务器提交一个什么样的数据)
Content-Type: application/x-www-form-unlencoded(请求的数据是以form表单的形式进行提交的)
username=zhangsan&passsword=123(这部分就是在url中携带的要交给服务器的数据)

LoginServlet代码:

package login;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.先从请求中拿到用户名和密码
        //为了保证读出来的参数也能支持中文,要记得设置编码方式是 utf8
        req.setCharacterEncoding("utf8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        //2.验证用户名和密码是否正确
        if (username == null || password == null || username.equals("") || password.equals("")) {
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("当前输入的用户名和密码不能为空!");
            return;
        }
        //此处假设用户名只能是 zhangsan 或者是 lisi,密码都是123
        if (!username.equals("zhangsan") && !username.equals("lisi")) {
            //用户名有问题
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("用户名或者密码有误!");
            return;
        }
        if (!password.equals("123")) {
            //密码有问题
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("用户名或者密码有误");
            return;
        }
        //3. 用户名和密码都ok,此时就创建一个session会话,因为用户刚开始登录的时候是没有sessionId的
        //当前用户是未登录的状态,此时请求的cookie没有sessionId
        //此处的getSession是无法从服务器的 哈希表中查村到 该session对象的
        //此处的参数是设为true,是允许在getSession在查询不到的时候,创建新的session和sessionId的
        //并且会把这个session对象和sessionId 存储到哈希表中
        //同时返回这个session对象,并且在后续的响应中自动把这个sessionId返回给客户端浏览器
        HttpSession session = req.getSession(true);
        //然后让刚创建好的session对象存储自己写的自定义的数据,就可以在这个对象中存储用户的身份信息
        session.setAttribute("username",username);
        //session对象本身可以看成一个哈希表,可以存储键值对,key必须是String类型的,值是object类型的
        //4.登录成功之后,自动跳转到index主页
        resp.sendRedirect("index");
    }
}

验证用户登录要做的几个步骤:

1. 读取用户名和密码(先拿到用户名和密码才能验证数据是否是正确的)
2. 验证用户民密码是否正确(正常的登录程序药用数据库进行查询的,此处只是简单的约定用户名只能是zhangsan 或者 lisi,密码都是123)
3. 创建会话,保存必要的用户信息(因为此时是用户第一次进行登录,所以getSession中的参数药设置为true,允许创建一个会话,保存用户的登录信息)
4. 重定向(如果用户名和密码都是ok的,此时就跳转到另一个html界面,告知用户 “欢迎xxx”,此时用户就知道登录成功了),这个跳转页面就是用响应的重定向实现的。

编写主页的Servlet(登录成功之后跳转到的页面)

package login;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

//这个Servlet用来动态的生成主页面
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //此处禁止创建会话,如果没找到,用户就是未登录状态
        //如果找到了才认为是登录状态
        //这里和前边的创建session不一样,这里的目的只能是查询
        //要想创建,就必须是登录成功之后才能创建
        //此处浏览器跳转到这个界面,没有登录也不能创建session了
       HttpSession session = req.getSession(false);
       if (session == null) {
           //当前是未登录状态
           resp.setContentType("text/html;charset=utf8");
           resp.getWriter().write("当前用户未登录!");
           return;
       }
       //此时如果有session了并且登录成功了,就把这个username拿到
        //此时这个session和刚才未登录时创建的session时同一个对象,这因为sessionId是一样的
        //这里得到的username对应的value是object类型,需要强转成String类型
       String username = (String) session.getAttribute("username");
       if (username == null) {
           //虽然有session对象,但是里面没有必要的属性,我们也认为是登录状态异常
           resp.setContentType("text/html;charset=utf8");
           resp.getWriter().write("当前用户未登录!");
           return;
       }

       //如果上述的校验都是ok的,此时就生成一个动态的页面
       resp.setContentType("text/html;charset=utf8");
       resp.getWriter().write("欢迎你!" + username);
    }
}

 index页面需要做的几个步骤:

1. 跳转之后首先验证用户的身份(如果登录过,在登录时就会创建一个session),所以跳转页面不可以创建会话,只能是拿着这个session去服务器中查询,如果没有找到session则认为是未登录状态。

2. 如果找到了,就是登录状态,之后根据查到的session(此时这个session和刚才创建的session是一个session对象)拿到刚才登陆时存储的用户名。

3. 根据用户名在跳转之后的页面中返回一个响应。(欢迎xxx)

    注:刚才创建的session对象和登录之后查询的session对象是同一个对象,因为此时是同一个sessionId,刚才登录成功之后,sessionId会通过Set-Cookie返回给浏览器,浏览器下次访问IndexServlet的时候,就会带上这个同一个的sessiuonId,然后Indexservlet中拿着这个sessionId再查询,就查到了同一个session对象。

登录功能运行效果:

 

session会话是否会持久化保存?

    session会话不会一直存在,比如:服务器重启之后,原来hash表中的内容就没有了,此时再次访问,就会出现sessionId没有查询到,此时会被识别成“未登录状态”。

    服务器默认保存会话,是在内存中的,一旦重启服务器,此时会话的数据就没了。

    但是Smart Tomcat 例外,为了方便程序猿调试,它会在停止服务器时,把会话持久化保存,并且在下次启动的时候,自动把会话恢复到内存中。(此时会话是不会丢失的,但是这个流程是否生效和tomcat的版本是有关的)

    但是如果是手动部署程序到Tomcat,则默认会话还是在内存中进行保存的,重启会丢失会话。

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

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

相关文章

docker cgroup资源占用及docker的镜像创建

cgroup用来资源限制 包括cpu&#xff0c;内存&#xff0c;磁盘三大方面 基本复写了常见的资源配额和使用量控制 cgroup是controlgroup的缩写 设置cpu使用率的上限 linux通过cfs&#xff08;完全公平调度器&#xff09;来调度各个进程对cpu的使用&#xff0c;cfs默认的调度…

Maven 介绍,根据 Maven 官方文档整理

这部分内容主要根据 Maven 官方文档整理&#xff0c;做了对应的删减&#xff0c;主要保留比较重要的部分&#xff0c;不涉及实战&#xff0c;主要是一些重要概念的介绍。 Maven 介绍 Maven 官方文档是这样介绍的 Maven 的&#xff1a; Apache Maven is a software project man…

OpenGL 着色器简介

1.简介 着色器(Shader)是运行在GPU上的小程序。这些小程序为图形渲染管线的某个特定部分而运行。从基本意义上来说&#xff0c;着色器只是一种把输入转化为输出的程序。着色器也是一种非常独立的程序&#xff0c;因为它们之间不能相互通信&#xff1b;它们之间唯一的沟通只有通…

Python数据攻略-DataFrame的数据计算和整理

大家好&#xff0c;我是Mr数据杨。今天&#xff0c;我们要踏上一场探索Python的旅程&#xff0c;途中我们将讲解算术运算、NumPy和SciPy函数的应用、DataFrame的排序、过滤、统计和遍历等技巧。想象一下如果《三国演义》中的诸葛亮有了Python的帮助&#xff0c;他将如何更有效地…

java debug调试工具

文章目录 java debug调试工具debugdebug运行断点如何运行 具体使用step intostep into Force step intoresume programstopview breakpointsmute breakpointsstep ourt Shift消除debug java debug调试工具 debug 就是调试工具&#xff0c;用来查看代码在运行工程数据的变化。 …

尚硅谷大数据hadoop教程_yarn

p125 课程介绍 p126 yarn基础架构 YARN主要由ResourceManager、NodeManager、ApplicationMaster和Container等组件构成。 p127 工作机制 &#xff08;1&#xff09;MR程序提交到客户端所在的节点。 &#xff08;2&#xff09;YarnRunner向ResourceManager申请一个Applicatio…

一本书让你彻底搞懂安卓系统性能优化(文末送书5本)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

c盘清理软件:清理垃圾、扩大c盘和系统迁移

一、为什么要c盘清理软件 Windows系统采用了NTFS文件系统&#xff0c;这种文件系统特点是有文件碎片和系统产生的临时文件会大量存储到系统盘上&#xff0c;而且在使用电脑的过程中&#xff0c;由于程序的安装、升级、卸载和其他操作会产生大量无用的垃圾文件&#xff0c;这些…

文心一言 VS 讯飞星火 VS chatgpt (32)-- 算法导论5.2 4题

四、利用指示器随机变量来解如下的帽子核对问题(hat-heck problem):n位顾客&#xff0c;他们每个人给餐厅核对帽子的服务生一顶帽子。服务生以随机顺序将帽子归还给顾客。请问拿到自己帽子的客户的期望数是多少? 文心一言&#xff1a; 我们可以将这个问题转化为求解在指示器…

Java的Comparator升序降序的记法

在使用Java自带的排序函数时&#xff0c;往往需要根据自己的需求自定义比较器。以前一直对Comparator的升序降序疑惑。现在记录一下&#xff0c;加深下印象。 先给结论&#xff1a; 实现Comparator接口&#xff0c;必须实现下面这个函数&#xff1a; Override public int co…

Vue+springboot电动车共享电池租赁管理系统设计与实现

基于java语言、Springboot框架、B/S架构、Mysql数据库设计并实现了共享电动车电池管理系统设计与实现。系统主要包括首页、个人中心、用户管理、维护人员管理、商户管理、区域信息管理、电池信息管理、租赁订单管理、归还订单管理、费用订单和定、提醒信息管理、维护信息管理、…

基于vue3+mqtt实现的远程串口实时调试助手(网络透传)

软件&#xff1a;串口调试助手&#xff08;基于MQTT消息协议实现多客户端同时订阅模式&#xff09; 扩展&#xff1a;手机端H5(websocket&#xff09;和vue3mqtt实现的接收客户端 用途&#xff1a;本地化串口调试&#xff0c;远程技术支持时可用&#xff0c;实时同步透传&…

Docker容器操作

#容器创建&#xff1a;就是将镜像加载到容器的过程。 新创建的容器默认处于停止状态&#xff0c;不运行任何程序&#xff0c;需要在其中发起一个进程来启动容器。 格式&#xff1a;docker create [选项] 镜像 常用选项&#xff1a; -i&#xff1a;让容器开启标准输入接受用户输…

2023年下半年,智能家居渠道有什么新趋势?

2023年&#xff0c;全国各地陆续释放利好政策的信号&#xff0c;商务部将今年定位为“消费提振年”&#xff0c;照明与家居建材行业的市场环境及消费潜力将会得到大幅度改善。随着产业升级与消费需求升级&#xff0c;近年来&#xff0c;智慧照明与智能家居和智慧整装的融合趋势…

Mac - 鼠标拖尾特效 By CursorEffect2

目录 一.引言 二.安装 CursorEffect2 三.使用 CursorEffect2 四.使用效果 五.内存消耗 六.一键关闭 七.总结 一.引言 在自己搭建的 Hexo 博客上可以定义鼠标点击的特效&#xff0c;如图点击后可以产生彩色的斑点。 于是想着除了浏览 Hexo 博客外&#xff0c;能不能别的也…

超黑光摄像机可以有多“黑“?

目前&#xff0c;市场标准黑光级IPC能在0.0005Lux(照度单位)的低照下维持彩色&#xff0c;但星光级或普通红外条件则必须依赖补光灯。那么有没有一款摄像机能达到超黑光的标准&#xff0c;能够在更暗环境下&#xff0c;不需要额外补光的情况下维持彩色呢&#xff1f; 超低照成像…

STM32接收串口数据并且存储SD,Python读取SD验证

在我们使用 STM32 或者 FPGA 采集数据的时候&#xff0c;需要将数据存储到SD卡中&#xff0c;因为数据是按照地址存储的&#xff0c;并且没有文件结构&#xff0c;所以不能直接用电脑的文件管理器读取&#xff0c;下面是一种读取数据的办法 0. 实验平台 正点原子STM32F407ZG探…

mysql 是否包含 返回索引 截取字符串

是否包含返回索引 原文链接&#xff1a;https://www.cnblogs.com/shoshana-kong/p/16474175.html 方法1&#xff1a;使用通配符%。 通配符也就是模糊匹配&#xff0c;可以分为前导模糊查询、后导模糊查询和全导匹配查询&#xff0c;适用于查询某个字符串中是否包含另一个模糊…

TCP协议是如何实现可靠传输的

一、TCP最主要的特点 1.TCP 是面向连接的运输层协议&#xff0c;在无连接的、不可靠的 IP 网络服务基础之上提供可靠交付的服务。为此&#xff0c;在 IP 的数据报服务基础之上&#xff0c;增加了保证可靠性的一系列措施。 2.TCP最主要的特点 &#xff08;1&#xff09;TCP 是…

SpringBootWeb AOP(上)

事务&AOP 1. 事务管理 1.1 事务回顾 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位。事务会把所有的操作作为一个整体&#xff0c;一起向数据库提交或者是撤销操作请求。所以这组操作要么同时成功&#xff0c;要么同时失败。 怎么样来控制这组操作&…