Cookie 和 Session机制

news2024/11/17 22:47:17

 Cookie

HTTP 协议自身是属于 "无状态" 协议.

"无状态" 的含义指的是:

默认情况下 HTTP 协议的客户端和服务器之间的这次通信, 和下次通信之间没有直接的联系.

但是实际开发中, 我们很多时候是需要知道请求之间的关联关系的.

例如登陆网站成功后, 第二次访问的时候服务器就能知道该请求是否是已经登陆过了

cookie内容是什么

cookie登录过程

图中的 "令牌" 通常就存储在 Cookie 字段中.

此时在服务器这边就需要记录令牌信息, 以及令牌对应的用户信息, 这个就是 Session 机制所做的工作.

cookie从哪里来

Cookie 中存储了一个字符串,

这个数据可能是客户端(网页)自行通过 JS 写入的,

也可能来自于服务器(服务器在 HTTP 响应的 header 中通过 Set-Cookie 字段把cookie的键值对, 返回给浏览器, 之后再在本地存储).

cookie功能之身份标识

cookie可以在浏览器存储一些"临时性的数据", 其中最典型的一种使用方式就是用来存储"身份标识"

往往可以通过这个字段实现 "身份标识" 的功能.

为了实现身份识别的效果, 不仅仅需要cookie来支持, 在服务器这边也需要一个session机制来支持

后续访问网站的其他页面, 就相当于我去各个科室做检查, 都会在请求的cookie字段中, 带上刚才这里的sessionId(也就是我到了科室, 人家让我先刷就诊卡), 服务器就可以根据sessionId 就知道你的身份信息, 就知道是哪个用户在操作了.

涉及到Cookie和Session 之间的联动

cookie 的本质是浏览器在本地存储 用户自定义数据的一种关键机制

cookie存储在哪里? 怎么存?

浏览器按照不同"服务器域名"存储不同的Cookie

不同域名之间的Cookie是不能干扰的

既然是需要存储, 怎么存?

直接存储到硬盘上是不行的, 不能允许网页能够操作你的电脑文件系统,  为了保证用户上网安全, 浏览器会限制网页直接访问硬盘.

浏览器虽然禁止了直接访问硬盘, 但提供了cookie机制, 允许网页往浏览器这边存储一些自定义的键值对, 这些数据通过了浏览器提供的api 写入特定的文件中

所以cookie是间接存储在浏览器所在电脑的硬盘上

Cookie 存储往往有一个超时间, 超过时间限制就删除了

cookie的内容到哪里去?

后续再访问这个网站中的各个页面, 就会在HTTP请求中自动带上cookie, 服务器就可以进一步的知道客户端的详细资料了(刚才去看病, 各个科室刷就诊卡)

cookie在浏览器这边只能算是"暂存"

真正要让这个数据发挥作用, 还得是服务器来使用

理解会话机制 (Session)

服务器同一时刻收到的请求是很多的. 服务器需要清除的区分清楚每个请求是从属于哪个用户, 就需要在服务器这边记录每个用户令牌以及用户的信息的对应关系.

在上面的例子中, 就诊卡就是一张 "令牌". 要想让这个令牌能够生效, 就需要医院这边通过系统记录每个就诊卡和患者信息之间的关联关系.

会话的本质就是一个 "哈希表", 存储了一些键值对结构. key 就是令牌的 ID(token/sessionId), value就是用户信息(用户信息可以根据需求灵活设计).

sessionId 是由服务器生成的一个 "唯一性字符串", 从 session 机制的角度来看, 这个唯一性字符串称为 "sessionId". 但是站在整个登录流程中看待, 也可把这个唯一性字符串称为 "token".

sessionId 和 token 就可以理解成是同一个东西的不同叫法(不同视角的叫法).

  • 当用户登陆的时候, 服务器在 Session 中新增一个新记录, 并把 sessionId / token 返回给客户端. (例如通过 HTTP 响应中的 Set-Cookie 字段返回).
  • 客户端后续再给服务器发送请求的时候, 需要在请求中带上 sessionId/ token. (例如通过 HTTP 请求中的 Cookie 字段带上).
  • 服务器收到请求之后, 根据请求中的 sessionId / token 在 Session 信息中获取到对应的用户信息, 再进行后续操作.

Servlet 的 Session 默认是保存在内存中的. 如果重启服务器则 Session 数据就会丢失.

Cookie Session 的区别

  • Cookie 是客户端的机制. Session 是服务器端的机制.
  • Cookie 和 Session 经常会在一起配合使用. 但是不是必须配合.
  1. 完全可以用 Cookie 来保存一些数据在客户端. 这些数据不一定是用户身份信息, 也不一定是 token / sessionId
  2. Session 中的 token / sessionId 也不需要非得通过 Cookie / Set-Cookie 传递.

核心方法  

HttpServletRequest 类中的相关方法

 返回值是一个数组, 每个元素是一个Cookie对象, 每个Cookie对象都是有键 也有值

Cookie 类中的相关方法
每个 Cookie 对象就是一个键值对 

   HttpServletResponse 类中的相关方法

 例一

@WebServlet("/getcookie")
public class GetCookieServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取这次请求中的Cookie
        Cookie[] cookies = req.getCookies();
        if(cookies != null) {
            for(Cookie cookie : cookies) {
                System.out.println(cookie.getName() + ":" + cookie.getValue());
            }
        }else {
            System.out.println("请求中没有cookie ok");
        }
        resp.getWriter().write("ok");
    }
}

使用费德勒进行抓包发现这这个请求里边并没有cookie

 因此我们需要设置cookie

@WebServlet("/setcookie")
public class SetCookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // t通过这个方法 设置自定义的cookie 并返回到浏览器这边
        Cookie cookie = new Cookie("test", "2023-09-23");
        resp.addCookie(cookie);
        Cookie cookie2 = new Cookie("time", "15:17");
        resp.addCookie(cookie2);
        resp.getWriter().write("set cookie ok");
    }
}

 

当访问setcookie 请求 , 代码就会构造set- cookie字段 并放到请求响应resp中, 一并返回给浏览器

此时再访问getcookie, 就有cookie了 

可以看到浏览器已经有了我们自定义的cookie 

例二 

sesion api 涵盖了cookie api

HttpServletRequest 类中的相关方法
 
HttpSession 类中的相关方法
一个 HttpSession 对象里面包含多个键值对 . 我们可以往 HttpSession 中存任何我们需要的信息.

 

 通过一个登录页面 进一步理解cookie 和 session 的关系

服务器后端代码如下: 

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1. 获取到用户名和密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if(username == null || password == null || username.equals("") || password.equals("")) {
            resp.setContentType("text/html; charset=utf-8");
            resp.getWriter().write("请求参数不完整");
            return;
        }

        // 2. 验证用户名密码是否正确了
        // 正常的验证, 是从数据库中读取数据
        // 注册账号就会给数据库插入用户名和密码. 登陆的时候就是验证当前用户名是否存在,以及密码是否匹配
        // 当前为了简单, 先不引入数据库, 直接通过编码的方式来判定用户名密码
        // 直接定义, 唯一合法的用户名是 zhangsan 密码是123
        if(!username.equals("zhangsan")) {
            resp.setContentType("text/html; charset=utf-8");
            resp.getWriter().write("用户名错误!");
            return;
        }
        if(!password.equals("123")) {
            resp.setContentType("text/html; charset=utf-8");
            resp.getWriter().write("密码错误");
            return;
        }

        // 3. 登录成功 此时可以给这个用户 创建会话了
        HttpSession session = req.getSession(true);
        // 在会话中, 可以顺便保存点自定义的数据, 比如保存一个登录的时间戳
        // setAttribute 后面的value 是一个object 想存啥都可以
        session.setAttribute("username", username);
        session.setAttribute("time", System.currentTimeMillis());

        // 4. 让页面自动转到网站主页.
        // 此处约定主页的路径是 index (也使用Servlet 生成一个动态页面)
        resp.sendRedirect("index");
    }
}
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 先验证一下用户的登录状态, 如果未登录, 就要求用户先登录一下
        HttpSession session = req.getSession(false);
        if(session == null) {
            resp.setContentType("text/html; charset=utf-8");
            resp.getWriter().write("请先登录, 再访问主页");
            return;
        }
        // 已经登录成功了
        // 就可以取出之前 attribute
        String username = (String) session.getAttribute("username");
        Long time = (Long) session.getAttribute("time");
        System.out.println("username" + username + ",time" + time);
        //
        resp.setContentType("text/html; charset=utf-8");
        resp.getWriter().write("欢迎您," + username + "! 上次登录时间" + time);

    }
}

 

 具体演示:

HttpSession session = req.getSession(true);

我们先通过login.html页面 向/login发送一个post登录请求(下图), 可见请求中 并未带有cookie 字段

而post请求返回的响应中 已经带有设定好的set-cookie字段, 这个字段就是返回给浏览器, 之后被浏览器存储为cookie

resp.sendRedirect("index");

之后重定向, 浏览器向主页面index  发送get请求, 可以看到此时请求中已经带有cookie

// 先验证一下用户的登录状态, 如果未登录, 就要求用户先登录一下
HttpSession session = req.getSession(false);

此时会话存在且有cookie, 则取cookie中的JsessionId对照服务器中的session(二者一定是一一对照的), 对照成功后返回该session

而此时新建一个页面进行登录操作, 已经带有先前设定好的cookie了

 

回复的响应中也不再需要set-cookie字段 

 

还有一处细节

同一个会话session 中先后设置了不同的属性Attributes, 所以返回时间不一样

 

// 在会话中, 可以顺便保存点自定义的数据, 比如保存一个登录的时间戳
// setAttribute 后面的value 是一个object 想存啥都可以
session.setAttribute("username", username);
session.setAttribute("time", System.currentTimeMillis());

 

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

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

相关文章

C++ -- IO流

目录 C语言的输入与输出 CIO流 C标准IO流 C文件IO流 文件常见的打开方式如下 以二进制的形式操作文件 以文本的形式操作文件 读写结构体 stringstream的简单介绍 C语言的输入与输出 C语言中我们用到的最频繁的输入输出方式就是scanf ()与printf()。 scanf(): 从标准输…

“构建可靠的前端测试环境与主页搭建实践“

目录 引言1. Mock.js的安装配置及使用1.1 安装Mock.js1.2 引入mockjs造假数据 2. 主页搭建实践1.1 设计主页结构配置路由 总结 引言 在现代软件开发中,前端测试和主页搭建是至关重要的环节。本文将介绍如何使用Mock.js进行安装配置和使用,并探讨如何构建…

解决方案|法大大电子签:3招击破汽车销售效率及成本难题!

近日,国家发改委、工业和信息化部、公安部等13部门联合发布《关于促进汽车消费的若干措施》,进一步稳定和扩大汽车消费,优化汽车购买使用管理制度和市场环境,更大力度促进新能源汽车持续健康发展。主要措施包含支持老旧汽车更新消…

云原生Kubernetes:K8S资源控制之污点与容忍

目录 一、理论 1.污点 2.容忍 3. Pod启动阶段 4. 故障排除步骤 5.对节点执行维护操作 二、实验 1.污点 2.容忍 三、问题 1.pod上配置容忍生成资源报错 四、总结 一、理论 1.污点 (1)作用 节点亲和性,是Pod的一种属性(偏好或硬性要求) ,它…

基于Java的超市进销存系统springboot18

大家好✌!我是CZ淡陌。一名专注以理论为基础实战为主的技术博主,将再这里为大家分享优质的实战项目,本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目,希望你能有所收获,少走一些弯路…

软件测试内容整理

1. 软件测试 1.1. 定义 软件测试(英语:Software Testing),描述一种用来促进鉴定软件的正确性、完整性、安全性和质量的过程。换句话说,软件测试是一种实际输出与预期输出之间的审核或者比较过程。 软件测试的经典定…

vue微前端qiankun框架学习到项目实战

微前端架构 一、什么是微前端架构 微前端是一种多个团队通过独立发布功能的方式来共同构建现代化web应用的技术手段及方法策略。 微前端借鉴了微服务的架构理念,将一个庞大的前端应用才分为多个独立灵活的小型应用,每个应用都可以独立开发&#…

lazada商品详情数据接口,支持多个国家站点

Lazada商品详情数据接口是一个RESTful风格的接口,通过HTTP协议来访问和操作资源。 Lazada商品详情API接口的使用方法如下: 获取Lazada平台上指定商品的详细信息,包括商品名称、价格、库存、分类、描述、图片等。支持通过商品ID、SKU、Selle…

短视频矩阵系统源码saas开发技术搭建代部署

一、短视频矩阵系统建模----技术api接口--获取用户授权 技术文档分享: 本系统采用MySQL数据库进行存储,数据库设计如下: 1.用户表(user): - 用户ID(user_id) - 用户名&#xff0…

十大直线导轨品牌

在现如今的制造业领域中,直线导轨作为重要的传动元件,广泛应用于各种机械装置中,以下是十个在直线导轨领域具有优秀表现的品牌,我们一起来看看: 1、日本THK,致力于开发、生产并且销售LM滚动导轨、滚珠花键、…

php eayswoole node axios crypto-js 实现大文件分片上传复盘

不啰嗦 直接上步骤 步骤1.开发环境配置 项目需要node.js 做前端支撑 官网下载地址: http://nodejs.cn/download/ 根据自己需要下载对应的版本,我下载的是windows系统64位的版本。 包下载好后 进行安装,安装步骤在此省略... 测试是否安装成功 如果是window 按住键…

WorkPlus Meet 视频会议,自主可控,支持私有化部署

在数字化时代,视频会议成为企业沟通和协作的重要工具。然而,许多企业对于数据安全和隐私保护的担忧使得选择合适的视频会议平台变得十分关键。作为一款具有私有化部署能力的视频会议工具,WorkPlus Meet完美替代了SaaS的腾讯视频会议&#xff…

HarmonyOS 4.0 实况窗上线!支付宝实现医疗场景智能提醒

本文转载自支付宝体验科技,作者是蚂蚁集团客户端工程师博欢,介绍了支付宝如何基于 HarmonyOS 4.0 实况窗实现医疗场景履约智能提醒。 1.话题背景 8 月 4 日,华为在 HDC(华为 2023 开发者大会)上推出了新版本操作系统…

TensorFlow入门(一)

一、下载安装Anaconda 下载地址:http://www.anaconda.comhttp://www.anaconda.com 下载完成后运行exe进行安装 二、下载cuda 下载地址:http://developer.nvidia.com/cuda-downloadshttp://developer.nvidia.com/cuda-downloads 下载完成后运行exe进行安装 安装后winR cmd进…

带权并查集

题目 并查集相信大家都不陌生,能够以极低的时间复杂度进行区间合并和区间查询,而带权并查集就是在此基础上新增了查询和维护节点到根节点距离的功能,注意此处所说的距离并不是并查集树形数据结构里节点之间的距离,而是题目里面描…

SpringBoot整合阿里云发送短信 (demo)

1. 登录阿里云 - 搜索【短信服务】- 套餐【立即购买】 2. 添加签名 国内消息 - 签名管理 - 添加签名 3. 添加模板 国内消息 - 模板管理 - 添加模板 模板详细 4. 依赖 <!--阿里云短信服务--> <dependency><groupId>com.aliyun</groupId><artifactI…

中国城市政商关系健康总指数、方面指数及一级指标得分2018

中国城市政商关系健康总指数、方面指数及一级指标得分2018 1、指标&#xff1a;省份代码、省份、城市代码、城市名称、政商关系健康指数、亲近指数、清白指数、政府关心、政府服务、企业税负、政府廉洁度、政府透明度 2、范围&#xff1a;290个地级市 3、数据说明&#xff1…

IDEA新建.xml文件显示为普通文本

情况如下&#xff1a; 1. 在XML文件中添加*.xml的文件名模式 2. 在文本中&#xff0c;选中*.xml进行删除

MySQL篇-MySQL存储引擎详解

MySQL 执行流程是怎样的&#xff1f; 可以看到&#xff0c; MySQL 的架构共分为两层&#xff1a;Server 层和存储引擎层&#xff0c; Server 层负责建立连接、分析和执行 SQL。MySQL 大多数的核心功能模块都在这实现&#xff0c;主要包括连接器&#xff0c;查询缓存、解析器、…

Euro-NCAP-HWA测试流程中文版V1.1(2023发布)

定义 在本协议中,使用了以下术语: Vehicle undertest (VUT) – 指根据本规程测试的车辆,车上有碰撞前的碰撞缓解或避免系统 Global VehicleTarget (GVT) – 指本协议中使用的车辆目标,其定义见TB025—Euro-NCAP全球车辆目标规范v1.0 辅助其他车辆(SOV)--指最新的 AEB …