第十二章:会话控制
会话控制
文章目录
- 会话控制
- 一、介绍
- 二、cookie
- 2.1 cookie 是什么
- 2.2 cookie 的特点
- 2.3 cookie 的运行流程
- 2.4 浏览器操作 cookie
- 2.5 cookie 的代码操作
- (1)设置 cookie
- (2)读取 cookie
- (3)删除 cookie
- 三、session
- 3.1 session 是什么
- 3.2 session 的作用
- 3.3 session 运行流程
- 3.4 session 的代码操作
- (1)express-session 的安装与配置
- (2)express 中 session 操作
- 四、session 和 cookie 的区别
- 五、token
- 5.1 token 是什么
- 5.2 token 的作用
- 5.3 token 的工作流程
- 5.4 token 的特点
- 5.5 JWT
- 六、附录
- 6.1 本地域名
- 6.2 修改域名
- (1)操作流程
- (2)原理
一、介绍
所谓会话控制就是 对会话进行控制
HTTP 是一种无状态的协议,它没有办法区分多次的请求是否来自于同一个客户端,无法区分用户
而产品中又大量存在的这样的需求,所以我们需要通过**会话控制**来解决该问题
常见的会话控制技术有三种:
- cookie
- session
- token
二、cookie
2.1 cookie 是什么
cookie 是 HTTP 服务器发送到用户浏览器并保存在本地的一小块数据。简单的理解:
- cookie 是保存在浏览器端的一小块数据
- cookie 是按照域名划分保存的
简单示例:
| 域名 | cookie |
|---|---|
| www.baidu.com | a=100;b=200 |
| www.bilibili.com | xid=1020abce121;hm=112411213 |
| jd.com | x=100;ocw=12414cce |
2.2 cookie 的特点
- 浏览器向服务器发送请求时,会自动将 当前域名下 可用的 cookie 设置在请求头中,然后传递给服务器
- 这个请求头的名字也叫 cookie,所以将 cookie 理解为一个 HTTP 的请求头也是可以的
2.3 cookie 的运行流程
-
填写账号和密码校验身份,校验通过后下发 cookie

-
有了 cookie 之后,后续再向服务器发生请求时,就会自动携带 cookie

2.4 浏览器操作 cookie
浏览器对 cookie 的操作,使用相对较少,了解即可
- 禁用所有 cookie
- 删除 cookie
- 查看 cookie
不同浏览器中的 cookie 是相互独立的,不共享
2.5 cookie 的代码操作
(1)设置 cookie
-
不带时效性(会在浏览器关闭的时候,销毁)
res.cookie('键名', '键值') -
带时效性(通过 maxAge 设置 cookie 的存活时间,单位是毫秒)
// n 是一个数字,表示 n 毫秒 res.cookie('键名', '键值', {maxAge: n}) -
代码示例:
// 导入 express const express = require('express')// 创建应用对象 const app = express()// 设置 cookie app.get('/set-cookie', (req, res) => {// 不带时效性(会在浏览器关闭的时候,销毁)res.cookie('name', 'zhangsan')// 带时效性(通过 maxAge 设置 cookie 存活的时间,单位是毫秒)res.cookie('name', 'lisi', {maxAge: 30000})res.send('Cookie的设置') })// 启动服务 app.listen(3000)
(2)读取 cookie
-
首先安装一个工具包 cookie-parser
npm i cookie-parser -
导入并使用 cookie-parser
// 导入 cookie-parser(其实就是一个中间件) const cookieParser = require('cookie-parser')// 设置 cookieParser 中间件 app.use(cookieParser()) -
使用 req.cookies 来读取 cookie。代码示例:
// 导入 express const express = require('express') // 安装 cookie-parser npm i cookie-parser // 导入 cookie-parser(其实就是一个中间件) const cookieParser = require('cookie-parser')// 创建应用对象 const app = express() // 设置 cookieParser 中间件 app.use(cookieParser())// 读取 cookie(要实现该效果,要安装一个工具包 cookie-parser) app.get('/get-cookie', (req, res) => {console.log(req.cookies)res.send('cookie的读取') })// 启动服务 app.listen(3000)
(3)删除 cookie
-
实现删除 cookie 只需要调用 clearCookie 方法即可
res.clearCookie('键名') -
代码示例:
// 导入 express const express = require('express')// 创建应用对象 const app = express()// 删除 cookie app.get('/remove-cookie', (req, res) => {// 调用方法res.clearCookie('name')res.send('cookie的删除') })// 启动服务 app.listen(3000)
三、session
3.1 session 是什么
session 是保存在 服务器端的一块儿数据,保存当前访问用户的相关信息
3.2 session 的作用
实现会话控制,可以识别用户的身份,快速获取当前用户的相关信息
3.3 session 运行流程
-
填写账号和密码校验身份,校验通过后创建 session 信息,然后将 session_id 的值通过响应头返回给浏览器

-
有了 cookie,下次发生请求时会自动携带 cookie,服务器通过 cookie 中的 session_id 的值确定用户的身份

3.4 session 的代码操作
(1)express-session 的安装与配置
- 首先安装 express-session 和 connect-mongo
npm i express-session connect-mongo
- 导入 express-session 和 connect-mongo
const session = require('express-session')
const MongoStore = require('connect-mongo')
- 设置 session 的中间件
app.use(session({name: 'sid', //设置cookie的name,默认值是:connect.sidsecret: 'yuwenkai', //参与加密的字符串(又称签名;加盐)saveUninitialized: false, //是否为每次请求都设置一个cookie用来存储session的idresave: true, //是否在每次请求时重新保存sessionstore: MongoStore.create({mongoUrl: 'mongodb://127.0.0.1:27017/mongoose_test' //数据库的连接配置}),cookie: {httpOnly: true, //开启后前端无法通过 JS 操作maxAge: 1000 * 60 //这一条是控制 sessionID 的过期时间的!!!}
}))
(2)express 中 session 操作
- 设置 session
// 导入 express
const express = require('express')
// 导入 express-session connect-mongo
const session = require('express-session')
const MongoStore = require('connect-mongo')// 创建应用对象
const app = express()
// 设置 session 的中间件
app.use(session({name: 'sid', //设置cookie的name,默认值是:connect.sidsecret: 'yuwenkai', //参与加密的字符串(又称签名;加盐)saveUninitialized: false, //是否为每次请求都设置一个cookie用来存储session的idresave: true, //是否在每次请求时重新保存sessionstore: MongoStore.create({mongoUrl: 'mongodb://127.0.0.1:27017/mongoose_test' //数据库的连接配置}),cookie: {httpOnly: true, //开启后前端无法通过 JS 操作maxAge: 1000 * 60 * 5 //这一条是控制 sessionID 的过期时间的!!!}
}))// 设置 session
app.get('/login', (req, res) => {if(req.query.username === 'admin' && req.query.password === '123456') {// 设置 session 信息req.session.username = 'admin'req.session.uid = '25gtf414g9u8o'res.send('登录成功')}else {res.send('登录失败')}
})// 启动服务
app.listen(3000)
- 获取 session
// 导入 express
const express = require('express')
// 导入 express-session connect-mongo
const session = require('express-session')
const MongoStore = require('connect-mongo')// 创建应用对象
const app = express()
// 设置 session 的中间件
app.use(session({name: 'sid', //设置cookie的name,默认值是:connect.sidsecret: 'yuwenkai', //参与加密的字符串(又称签名;加盐)saveUninitialized: false, //是否为每次请求都设置一个cookie用来存储session的idresave: true, //是否在每次请求时重新保存sessionstore: MongoStore.create({mongoUrl: 'mongodb://127.0.0.1:27017/mongoose_test' //数据库的连接配置}),cookie: {httpOnly: true, //开启后前端无法通过 JS 操作maxAge: 1000 * 60 * 5 //这一条是控制 sessionID 的过期时间的!!!}
}))// 获取 session
app.get('/cart', (req, res) => {console.log(req.session.uid)if(req.session.username) {res.send(`购物车页面,欢迎${req.session.username}登录`)}else {res.send('登录失败')}
})// 启动服务
app.listen(3000)
- 销毁 session
// 导入 express
const express = require('express')
// 导入 express-session connect-mongo
const session = require('express-session')
const MongoStore = require('connect-mongo')// 创建应用对象
const app = express()
// 设置 session 的中间件
app.use(session({name: 'sid', //设置cookie的name,默认值是:connect.sidsecret: 'yuwenkai', //参与加密的字符串(又称签名;加盐)saveUninitialized: false, //是否为每次请求都设置一个cookie用来存储session的idresave: true, //是否在每次请求时重新保存sessionstore: MongoStore.create({mongoUrl: 'mongodb://127.0.0.1:27017/mongoose_test' //数据库的连接配置}),cookie: {httpOnly: true, //开启后前端无法通过 JS 操作maxAge: 1000 * 60 * 5 //这一条是控制 sessionID 的过期时间的!!!}
}))// 销毁 session
app.get('/logout', (req, res) => {req.session.destroy(() => {res.send('退出成功')})
})// 启动服务
app.listen(3000)
四、session 和 cookie 的区别
cookie 和 session 的区别主要有如下几点:
- 存放的位置
- cookie:浏览器端
- session:服务端
- 安全性
- cookie 是以明文的方式存放在客户端的,安全性相对较低
- session 存放于服务器中,所以安全性 相对 较好
- 网络传输量
- cookie 设置内容过多会增大报文体积,会影响传输效率
- session 数据存储在服务器,只是通过 cookie 传递 id,所以不影响传输效率
- 存储限制
- 浏览器限制单个 cookie 保存的数据不能超过 4K,且单个域名下的存储数量也有限制
- session 数据存储在服务器中,所以没有这些限制
五、token
5.1 token 是什么
token 是服务端生成并返回给 HTTP 客户端的一串加密字符串,token 中保存着 用户信息
5.2 token 的作用
实现会话控制,可以识别用户的身份,主要用于移动端 APP
5.3 token 的工作流程
-
填写账号和密码校验身份,校验通过后响应 token,token 一般是在响应体中返回给客户端的

-
后续发送请求时,需要手动将 token 添加到请求报文中,一般是放在请求头中

5.4 token 的特点
- 服务端压力更小
- 数据存储在客户端
- 相对更安全
- 数据加密
- 可以避免 CSRF(跨站请求伪造)
- 扩展性更强
- 服务间可以共享
- 增加服务节点更简单
5.5 JWT
JWT(JSON Web Token)是目前最流行的跨域认证解决方案,可用于基于 token 的身份验证
JWT 使 token 的生成与校验更规范,我们可以使用 jsonwebtoken 包 来操作token
-
安装 jsonwebtoken 包
npm i jsonwebtoken -
代码示例:
// 导入 jwt const jwt = require('jsonwebtoken')// 创建(生成)token // let token = jwt.sign(用户数据, 加密字符串, 配置对象) let token = jwt.sign({username: 'zhangsan' }, 'yuwenkai', {expiresIn: 60 //单位是秒 })console.log(token)// 校验token // jwt.verify(token, 加密字符串, 回调函数) jwt.verify(token, 'yuwenkai', (err, data) => {if(err) {console.log('校验失败!')return}console.log(data) })
扩展阅读:JSON Web Token 入门教程
六、附录
6.1 本地域名
所谓本地域名就是 只能在本机使用的域名,一般在开发阶段使用
6.2 修改域名
我们可以通过对 hosts 文件进行修改本地域名
(1)操作流程
编辑文件 C:\Windows\System32\drivers\etc\hosts
127.0.0.1 www.ywk.com
如果修改失败,可以修改该文件的权限

(2)原理
在地址栏输入 域名 之后,浏览器会先进行 DNS(Domain Name System)查询,获取该域名对应的 IP 地址
请求会发送到 DNS 服务器,可以 根据域名返回 IP 地址
可以通过 ipconfig /all 查看本机的 DNS 服务器
hosts 文件也可以设置域名与 IP 的映射关系,在发送请求前,可以通过该文件获取域名的 IP 地址
相关文章:
第十二章:会话控制
会话控制 文章目录 会话控制一、介绍二、cookie2.1 cookie 是什么2.2 cookie 的特点2.3 cookie 的运行流程2.4 浏览器操作 cookie2.5 cookie 的代码操作(1)设置 cookie(2)读取 cookie(3)删除 cookie 三、se…...
【LeetCode滑动窗口算法】长度最小的子数组 难度:中等
我们先看一下题目描述: 解法一:暴力枚举 时间复杂度:o(n^3) class Solution { public:int minSubArrayLen(int target, vector<int>& nums){int i 0, j 0;vector<int> v;for (;i < nums.size();i){int sum nums[i];fo…...
MySQL 用户权限管理:授权、撤销、密码更新和用户删除(图文解析)
目录 前言1. 授予权限2. 撤销权限3. 查询权限4. Demo 前言 公司内部的数据库权限一般针对不同人员有不同的权限分配,而不都统一给一个root权限 1. 授予权限 授予用户权限的基本命令是GRANT 可以授予的权限种类很多,涵盖从数据库和表级别到列和存储过…...
Day39
Day39 JSP JSP底层 全称为Java Server Pages,JSP实际上就是一个servelet JSP:HTML页面Java代码,本质:servlet。 public class login_jsp{//JSP的9大内置对象private JSPWriter out;//当前JSP输出流对象private HttpServletRequest request;…...
Nginx之HTTP模块详解
Nginx是模块化的代码架构,其代码由核心代码与功能模块代码构成。Nginx的主要功能模块是HTTP功能模块,HTTP功能模块在HTTP核心功能的基础上为Nginx对HTTP请求的处理流程提供了扩展功能,这些扩展功能可以让用户很方便地应对访问控制、数据处理、…...
JCR一区 | Matlab实现GAF-PCNN、GASF-CNN、GADF-CNN的多特征输入数据分类预测/故障诊断
JJCR一区 | Matlab实现GAF-PCNN、GASF-CNN、GADF-CNN的多特征输入数据分类预测/故障诊断 目录 JJCR一区 | Matlab实现GAF-PCNN、GASF-CNN、GADF-CNN的多特征输入数据分类预测/故障诊断分类效果格拉姆矩阵图GAF-PCNNGASF-CNNGADF-CNN 基本介绍程序设计参考资料 分类效果 格拉姆…...
最新Prompt预设词分享,DALL-E3文生图+文档分析
使用指南 直接复制使用 可以前往已经添加好Prompt预设的AI系统测试使用(可自定义添加使用) 支持GPTs SparkAi SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统,支持OpenAI-GPT全模型国内AI全模型。支持GPT-4o…...
基于SpringBoot+Vue会所产后护理系统设计和实现
基于SpringBootVue会所产后护理系统设计和实现 🍅 作者主页 网顺技术团队 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 🍅 文末获取源码联系方式 📝 🍅 查看下方微信号获取联系方式 承接各种定制系统 &#…...
Linux中的EINTR和EAGAIN错误码
Linux中的EINTR和EAGAIN错误码 在Linux系统中,进行系统调用时经常会遇到各种错误码。其中,EINTR(Interrupted system call)和EAGAIN(Resource temporarily unavailable)是两个较为常见的错误码,…...
用户需求分析揭秘:最佳实践与策略
大多数产品团队都有自己处理客户需求的一套流程。但是那些潜在的客户和他们的需求呢?如果在产品管理上已经有一定的资历,很可能对此见惯不怪了。 通常,这些需求是销售人员跑来告诉你的,大概就是说:“超棒的潜在客户一…...
批量创建文件夹 就是这么简单 一招创建1000+文件夹
批量创建文件夹 就是这么简单 一招创建1000文件夹 在工作中,或者生活中,我们经常要用到批量创建文件夹,并且根据不同的工作需求,要求是不一样的,比如有些人需要创建上千个不一样名称的文件夹,如果靠手动创…...
LogicFlow 学习笔记——8. LogicFlow 基础 事件 Event
事件 Event 当我们使用鼠标或其他方式与画布交互时,会触发对应的事件。通过监听这些事件,可以获取其在触发时所产生的数据,根据这些数据来实现需要的功能。详细可监听事件见事件API。 监听事件 lf实例上提供on方法支持监听事件。 lf.on(&…...
Nginx缓存之代理缓存配置
Nginx 的缓存功能是集成在代理模块中的,当启用缓存功能时,Nginx 将请求返回的响应数据持久化在服务器磁盘中,响应数据缓存的相关元数据、有效期及缓存内容等信息将被存储在定义的共享内存中。当收到客户端请求时,Nginx 会在共享内…...
【Android】使用SeekBar控制数据的滚动
项目需求 有一个文本数据比较长,需要在文本右侧加一个SeekBar,然后根据SeekBar的上下滚动来控制文本的滚动。 项目实现 我们使用TextView来显示文本,但是文本比较长的话,需要在TextView外面套一个ScrollView,但是我…...
新能源汽车的能源动脉:中国星坤汽车电缆在新能源汽车电气化中的应用!
随着新能源汽车行业的蓬勃发展,汽车电缆组件作为汽车电气系统的核心组成部分,其重要性日益凸显。中国星坤汽车电缆组件以其卓越的性能和创新技术,为汽车的电能传输、信号传递和控制提供了坚实的保障。本文将深入解析星坤汽车电缆组件的特性、…...
AVL许可证查询系统
在数字化时代,软件已经成为企业运营的核心组成部分。然而,随着软件应用的不断增加,许可证管理也变得越来越复杂。AVL许可证查询系统作为企业软件资产管理的重要工具,能够帮助企业实现对软件许可证的全面掌控。本文将深入探讨AVL许…...
四个步骤,帮你成为价值导向型项目经理
在企业数字化转型的浪潮下,项目管理的方向逐渐从任务导向转变为以价值交付为导向。在快速变化的市场环境中,仅仅关注项目任务的完成已不足以确保项目的成功,需要更加注重项目的最终成果和价值,确保项目能够为组织带来实际的价值和…...
Python3 使用 clickhouse-connect 操作 clickhouse
版本: Python 3.7 x86 clickhouse 24.6.1.3573 clickhouse-connect 0.6.22 代码一: # pip install clickhouse-connectimport clickhouse_connect# 准备参数 host "192.168.1.112" port 8123 username "default" passw…...
Python脚手架系列-DrissionPage
记录DrissionPage模块使用中的一些常常复用的代码,持续更新… 接管谷歌浏览器 from DrissionPage import ChromiumPage, ChromiumOptionsco ChromiumOptions().set_local_port(4249) driver ChromiumPage(addr_or_optsco)创建driver,如果浏览器已开启优先接管&am…...
Java中如何调用mysql中函数
在Java中调用MySQL中的函数(无论是存储函数还是自定义函数),通常是通过JDBC(Java Database Connectivity)来完成的。以下是一个简单的步骤说明和示例代码,展示如何在Java中调用MySQL中的函数。 步骤 添加…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...
AxureRP-Pro-Beta-Setup_114413.exe (6.0.0.2887)
Name:3ddown Serial:FiCGEezgdGoYILo8U/2MFyCWj0jZoJc/sziRRj2/ENvtEq7w1RH97k5MWctqVHA 注册用户名:Axure 序列号:8t3Yk/zu4cX601/seX6wBZgYRVj/lkC2PICCdO4sFKCCLx8mcCnccoylVb40lP...
用递归算法解锁「子集」问题 —— LeetCode 78题解析
文章目录 一、题目介绍二、递归思路详解:从决策树开始理解三、解法一:二叉决策树 DFS四、解法二:组合式回溯写法(推荐)五、解法对比 递归算法是编程中一种非常强大且常见的思想,它能够优雅地解决很多复杂的…...
