【Java EE初阶二十七】深入了解cookie

1. 简单了解cookie

        Cookie是http请求里header 中的一个属性,浏览器持久化存储数据的一种机制,网页无法访问主机的文件系统,要想存储数据就得通过其他的方式;

        且cookie中保存的数据也是键值对的形式,最终还是要把这个键值对发送回服务器,服务器要使用 Cookie 来完成一些业务逻辑;其中有一个特殊的情况,就是会使用 Cookie 存储当前用户的身份信息;

        我们当前坐火车的时候都需要身份证,此时当前的身份证就可以理解是我们每一个人的特有cookie,当我们在进行出站和进战的时候,就需要拿身份证在机器上扫描,这时候通过身份证就可以读取到我们坐车的相关信息,这些信息肯定是从服务器中接收到的,我们每一个人的出行信息必然是存储在数据库中的,在服务器代码的逻辑展开执行的过程中,这些数据就也会被从数据库査询出来,先临时的保存到某个内存结构(session)中,后续要是修改数据,就要重新写入数据库

        Cookie 是客户端存储数据的机制,Session 是服务器存储数据的机制(不算持久化存储),当然两者往往会相互配合使用的,

        在 cookie 中存储的用户身份标识,也经常会理解成 sessionld; 每个用户都有一个自己的 session, 也有不同的 séssionld;

        服务器会通过类似于 hash 这样的键值对结构来存储 session 的。sessionld 就是 key,session 本身就是 value,在 session 里面又可以存储各种的用户自身的信息 (也是程序员自定义的);

        下图是cookie和session之间工作的原理图解:

2. 深入了解cookie

        通过 Servlet api 来操作上述结构;

        Cookie 是浏览器的机制,,Servlet 提供了 api 获取到 Cookie.
        Session 是服务器的机制,Servlet 内部已经实现好了,也提供了 api 可以让我们进行使用。

        

        这个方法主要是给登录场景应用的,就能够完成从 cookie 中获取到 sessionld,并且查询出对应 session 的过程,如果 sessionld 没有从 hash 表查到,也能帮咱们自动的创建出新的键值对(分配新的 sessionld,以及创建一个新的 HttpSession 对象)

        servlet中通过 httpsession这个类表示一个会话,服务器上同时具有很多个会话,服务器上就会存在一个如下所示的会话,

2.1 实现登录的原理

1、登录页面(html)

        

        点击登录buttion之后发起一个 HTTP 请求,触发登录逻辑(带上用户输入的用户名和密码)

2、通过一个 Servlet 处理上述的登录请求
        通过这个 Servlet 读取用户名和密码,并且验证是否登录成功,如果登录成功,就会给当前这个用户,创建一个会话(保存用户当前的信息),并且把得到的 sessionld, 通过 cookie 返回给客户端(客户端就把 cookie 保存起来了)

3、网站主页,通过另一个 Servlet 生成的动态页面
        在这个页面中,就会把刚才这里的用户数据给显示到页面上,比如是使用"smallye" 用户来登录
,主页上就会显示"欢迎你 smallye" 这样的标语;

2.2 项目逐步编写

 1、先开始搞真被登陆页面

        此处的登录, 使用 json 也不是不可以,但是使用 json 就无法使用 form 表单了,使用json
就雲要通过 ajax 的方式构造请;同时接下来,服务器这边处理的逻辑, 就按照这个格式来处理

 2、写一个 Servlet 处理上述登录请求.

  

        这个方法,就是根据请求的 cookie 中的 sessionld,查询服务器的hash 表,找到对应的 session 对象,如果 cookie 中没有 sessionld(首次登录的时候,就是没有的),或者 sessionld 没有査找到对应的 session 对象,就可以创建出一个sesion 对象出来;即会创建出一个 sessionld 和一个 session 对象,把这个键值对保存到 hash 表里(会再响应报头中加上 Set-cookie 字段),servlet并且会把 sessionld 设置到响应中, 传回给浏览器, 让浏览器使用 Cookie 来保存;

        在该方法中的设置参数为 true,即允许在不存在时自动创建session对象.参数为 false则不能创建session对象, 直接返回 null;

        文里使用 Attribute 的作用, 主要就是为了让多个数据,在多个 Servlet 之间共享,同时 Attribute 是会话级别的.每个用户/客户端都是有自己的数据, 相互之间都不会有干扰;

3、关于多客户端显示的不同界面的问题

        如果这个 Servlet 是通过第一个浏览器调用的,此时Servlet 里面拿到的就是 zhangsan 这个 Session 对象,及其里面的数据;如果这个 Servlet是通过第二个浏监器调用的,此时 Servlet 里面拿到的就是 lisi 这个 Session 对象,及其里面的数据,通过 sessionld 取会话对象,(两个浏览器的sessionld 不同);

        综上所述,同样的页面,不同用户看到的数据肯定也是不同的,对于b站的页面我们自己访问这个页面看到的数据和其他人访问的这个页面看到的数据是必然是完全不同的;

        上述代码就是重定向跳转到 index 页面上(后续会写一个 Servlet 生成这个页面);

4、实现登录后的主页

        会话就可以理解成"用户身份信息”体现,在通过登录操作,验证了用户身份之后,才能够创建会话.,其他页面没有做"验证身份",不应该创建会话;

2.3 服务器代码如下

登录代码:

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. 读取请求传来的参数 (用户名和密码)
        //    最好先给请求设置一下字符集. 否则如果 username 是中文, 此处的 getParameter 可能会乱码.
        req.setCharacterEncoding("utf8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        // 2. 验证用户名密码, 是否是正确的. 一般来说, 验证用户名密码, 是要通过数据库的.
        //    此处为了简单一点, 先把用户名和密码, 写死. 比如此处假设正确的用户名是 zhangsan, 正确的密码是 123
        //    此处还要注意, 上述 getParameter 可能会拿到 null .  为了避免 空指针异常, 下面这种比较方式是更合适的写法.
        if (!"zhangsan".equals(username) || !"123".equals(password)) {
            // 登录失败
            // 给用户返回一个提示.
            resp.setContentType("text/html; charset=utf8");
            resp.getWriter().write("当前的用户名或者密码错误!");
            return;
        }
        // 3. 登录成功了, 给这个用户创建一个会话出来.
        //    可以给会话中保存一些自定义的数据, 通过 Attribute 的方式来保存.
        HttpSession session = req.getSession(true);
        //    此处 Attribute 也是键值对. 这里的内容存储什么都可以. 程序员自定义的.
        //    这样的数据存储好了之后, 后续跳转到其他的页面, 也随时可以把这个数据从会话中取出来.
        session.setAttribute("username", username);
        session.setAttribute("loginTime", System.currentTimeMillis());
        // 4. 此时相当于登录成功!! 让页面跳转到网站首页.
        resp.sendRedirect("index");
    }
}

重定向代码:

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 {
        // 1. 先获取到当前用户对应的会话对象. 生成的页面要根据当前用户信息来构造.
        HttpSession session = req.getSession(false);
        if (session == null) {
            // sessionId 不存在, 或者 sessionId 没有在 hash 表中查到.
            resp.setContentType("text/html; charset=utf8");
            resp.getWriter().write("您当前尚未登录!");
            return;
        }
        // 2. 从会话中拿到之前存储的用户信息
        //    此处的强转, 需要程序员自行保证, 类型是靠谱的.
        String username = (String) session.getAttribute("username");
        Long loginTime = (Long) session.getAttribute("loginTime");
        // 3. 生成一个页面, 把上述数据显示到页面上.
        resp.setContentType("text/html; charset=utf8");
        String respBody = "欢迎你 " + username + "! 上次登录时间为: " + loginTime;
        resp.getWriter().write(respBody);
    }
}

2.4 过程分析

1)、点击登录之后,就会触发一个 POST 请求

2)、服务器响应

        此处 getSession 会创建新会话:
        1、生成 sessionld 和 HttpSession对象

        2、把上述 sessionld 和 HttpSession 对象保存到 内存 hash 表中.
        3、把 sessionld 设置到响应报文的 header 中Set-Cookie 字段,如下所示:

        浏览器拿到响应,就会把这个 Set-Cookie 的内容保存到浏览器的 Cookie 中:

3、重定向到主页.(index)

        

3. 在说cookie和session

        浏览器首次访问登录操作的时候,就会在服务器这边验证身份。验证通过,就会创建会话,服务器就会保存会话信息 (hash),客户端也会保存身份标识(sessionld),后续浏览器再访问这个网站(网站的其他页面) 都会带上 cookie(sessionld),服务器不需要让浏览器重新登录,也能识别出浏览器的用户身份信息.

        一个网站,只要登录成功之后,后续访问这个网站的其他页面,也都是会处在一个 登录 状态
上述过程都是可以借助 cookie 和 session 来完成的;

        上述已登录的状态也会有时间限制,有的网站过期时间比较长(B 站),有的过期时间比较短.(网银),可以给 Cookie 设置过期时间,(即时间一到,浏览器就会自动把 Cookie 删除掉),也可以给 session 设置过期时间,(时间到,服务器自动删除会话 )

ps:关于cookie和session的深入学习就到这里了,如果大家感兴趣的话就请一键三连哦!!!

        

        

        

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Selenium的UI自动化测试屏幕截图功能实例代码

UI自动化测试执行过程中,当遇到检查失败的情况,往往会发现打印的log并不能有效地帮助我们定位问题。我们需要失败时刻的屏幕截图来重现当时的失败场景,进而排查出错原因。 基于这种需求可以使用Selenium的屏幕截图功能。 实现代码如下&…

程序计数器介绍

程序计数器是计算机处理器中的寄存器,它包含当前正在执行的指令的地址(位置)。当每个指令被获取,程序计数器的存储地址加一。在每个指令被获取之后,程序计数器指向顺序中的下一个指令。当计算机重启或复位时,程序计数器通常恢复到…

Matlab数值计算(多项式插值)

多项式插值问题 拉格朗日插值多项式 例1:在某个化学反应过程中,在有限个时刻t(min),测得生成物浓度y(g/)d的数据如下: 123468101214164.006.418.018.799.539.8610.3310.4210.5310.61 求在时刻t5分,t16.4分时的浓度是…

开发者如何选择代码签名证书?

代码签名证书是一种由权威认证机构颁发的数字证书,它允许软件开发者对其代码进行数字签名。这种签名基于公钥基础设施(PKI)技术,使用一对密钥:一个私钥和一个公钥。私钥用于生成签名,而公钥则嵌入到代码签名…

微信小程序开发:页面分享卡片、风格选择、通道启用等可配置

上文说到,我们部署了定时任务,但是有个地方忘记在上文写了,这里补上,就是定时任务的超时时间问题,超时时间有7200秒: 我们改成7100秒: 再把云函数调用的云对象的超时时间也改下: 超时…

20240306作业

1.编写一个伪终端&#xff1a;在真正的终端上运行这个伪终端程序之后&#xff0c;能够执行所有的shell指令&#xff0c;甚至再次运行自己 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h…

Vue3.2 + vue/cli-service 打包 chunk-vendors.js 文件过大导致页面加载缓慢解决方案

chunk-vendors.js 是/node_modules 目录下的所有模块打包成的包&#xff0c; 但是这包太大导致页面加载很慢&#xff08;我的都要3-4秒了&#xff09;&#xff0c; 这个时候就会出现白屏的情况 解决方案 1、compression-webpack-plugin 插件解决方案 1&#xff09;、安装 npm …

Docker数据卷篇

1. 数据卷&#xff08;容器数据管理&#xff09; 引言&#xff1a;在之前的nginx案例中&#xff0c;修改nginx的html页面时&#xff0c;需要进入nginx内部。并且因为没有编辑器&#xff0c;修改文件也很麻烦。 这就是因为容器与数据&#xff08;容器内文件&#xff09;耦合带…

用位运算维护状态码,同事直呼牛X!

位运算是一种非常高效的运算方式。在算法考察中比较常见&#xff0c;它使用位级别的操作来表示和控制状态&#xff0c;这在管理多个布尔标志或状态时尤其有用。那么业务代码中我们如何使用位运算呢&#xff1f; 位运算基础 我们先来回顾一下位运算的基础&#xff1a; 与&…

领到了腾讯云服务器红包,可以用于购买服务器,开心!

在2024年腾讯云新春采购节优惠活动上&#xff0c;可以领取新年惊喜红包&#xff0c;打开活动链接 https://curl.qcloud.com/oRMoSucP 会自动弹出红包领取窗口&#xff0c;如下图&#xff1a; 腾讯云2024新春采购节红包领取 如上图所示&#xff0c;点击“领”红包&#xff0c;每…

腾讯云十大优惠活动曝光,TOP10值得买云服务器配置报价

腾讯云服务器多少钱一年&#xff1f;61元一年起&#xff0c;2核2G3M配置&#xff0c;腾讯云2核4G5M轻量应用服务器165元一年、756元3年&#xff0c;4核16G12M服务器32元1个月、312元一年&#xff0c;8核32G22M服务器115元1个月、345元3个月&#xff0c;腾讯云服务器网txyfwq.co…

python爬虫(一)

一、python中的NumPy模块&#xff08;数据的存储和处理&#xff09; 这里是下载完成之后的表现 &#xff08;1&#xff09;创建数组 1、使用array&#xff08;&#xff09;函数创建数组 使用array函数可以创建任意维度的的数组 下面是一个创建二维数组的代码示例 下面是代码…

L1-096 谁管谁叫爹分数

L1-096 谁管谁叫爹 分数 20 全屏浏览 切换布局 作者 陈越 单位 浙江大学 《咱俩谁管谁叫爹》是网上一首搞笑饶舌歌曲&#xff0c;来源于东北酒桌上的助兴游戏。现在我们把这个游戏的难度拔高一点&#xff0c;多耗一些智商。 不妨设游戏中的两个人为 A 和 B。游戏开始后&…

使用统一功能完善图书管理系统

目录 一、前提 二、实现强制登陆传统方式 三、拦截器 1、概念 2、拦截器 &#xff08;1&#xff09;定义拦截器 &#xff08;2&#xff09;注册拦截器 &#xff08;3&#xff09;运行 3、使用拦截器实现强制登陆 4、DispatcherServlet源码解析 四、适配器模式 1、适…

Postman 接口自动化测试教程:入门介绍和从 0 到 1 搭建 Postman 接口自动化测试项目

关于Postman接口自动化测试的导引&#xff0c;全面介绍入门基础和从零开始搭建项目的步骤。学习如何有效地使用Postman进行API测试&#xff0c;了解项目搭建的基础结构、环境设置和测试用例的编写。无论您是新手还是经验丰富的测试人员&#xff0c;这篇教程都将为您提供清晰的指…

IIC 接口

IIC 接口 IIC总线概述IIC总线简介IIC总线通信过程IIC总线寻址方式 IIC总线信号实现起始信号、停止信号字节传送与应答同步信号 IIC典型时序 IIC总线概述 IIC总线简介 IIC总线是Philips公司在八十年代初推出的一种串行、半双工总线&#xff0c;主要用于近距离、低速的芯片之间…

SpringBoot集成图数据库neo4j实现简单的关联图谱

社交领域&#xff1a;Facebook, Twitter&#xff0c;Linkedin用它来管理社交关系&#xff0c;实现好友推荐 图数据库neo4j安装&#xff1a; 下载镜像&#xff1a;docker pull neo4j:3.5.0运行容器&#xff1a;docker run -d -p 7474:7474 -p 7687:7687 --name neo4j-3.5.0 ne…

信息熵、KL散度、交叉熵、互信息、点互信息

信息熵 信息量 信息量是对信息的度量&#xff0c;衡量事件的不确定性&#xff0c;越小概率的事件发生了产生的信息量越大。我们应该用什么形式的函数表达信息量呢&#xff1f;除了随着概率增大而减少&#xff0c;这个函数还有具有以下性质&#xff1a; 如果有两个事件x和y彼…

云消息队列 Confluent 版正式上线!

作者&#xff1a;阿里云消息队列 前言 在 2023 年杭州云栖大会上&#xff0c;Confluent 成为阿里云技术合作伙伴&#xff0c;在此基础上&#xff0c;双方展开了深度合作&#xff0c;并在今天&#xff08;3月1日&#xff09;正式上线“云消息队列 Confluent 版”。 通过将 Co…

vue3学习(续篇)

vue3学习(续篇) 默认有vue3基础并有一定python编程经验。 chrome浏览器安装vue.js devtools拓展。 文章目录 vue3学习(续篇)1. element-ui使用2. axios 网络请求1. 简介2. 操作 3. flask-cors解决跨域问题1. 简介2. 操作 4. 前端路由 vue-router1. 简单使用2. 配置路径别名和…