什么是会话固定以及如何在 Node.js 中防止它
什么是会话固定以及如何在 Node.js 中防止它
在深入讨论之前,我们需要了解会话是什么以及会话身份验证如何工作。
什么是会话?
正如我们所知,HTTP 请求是无状态的,这意味着当我们发送登录请求时,并且我们有有效的用户名和密码,没有默认机制可以知道我们是发送下一个请求的同一个人。为了解决这个问题,换句话说,使请求有状态,有一些常用的方法,如Cookie、隐藏表单字段、URL 参数、浏览器存储、JWT 和 Session。在本文中,我们将重点关注Session。
Session是存储在服务器上的数据。每个客户端都会获得一个与服务器上的数据相关的唯一标识符 。客户端必须在每个请求上发送此唯一标识符,以便我们知道谁发送了此请求。该标识符可以在 cookie 或 URL 参数中发送。
下面是使用express-session和express创建session的简单示例:
const app = require('express')();
const session = require('express-session');
app.use(require('cookie-parser')());
app.use(require('body-parser').json());app.use(session({secret: 'secret',cookie: { maxAge: 60000 },name: 'sessionId'
}));app.get('/', (req, res) => {res.send('ping');
});app.listen(3000, () => {console.log('Server is running on port 3000');
});
当第一次发送请求时,express-session中间件会创建一个新的唯一标识符,并将其设置为 cookie 后再将其存储在某处(在本例中为内存,但我们也可以传递自定义存储)。在会话中间件的选项中,我们使用了sessionId存储此唯一标识符的密钥名称。现在,如果我们发送请求,我们会看到如下内容:

浏览器现在设置此 cookie 并自动存储它以供进一步请求。如果我们发送包含有效会话的请求(该会话存在于我们的会话存储中 - 在本例中为内存),在响应中获取标头的标头就不再包含Set-Cookie字段了:

当用户登录时,我们可以将用户信息存储在 cookie 中(序列化),也可以将其存储在数据库中并将数据与sessionId进行绑定. 让我们使用 Map 作为我们的简单数据库:
const db = new Map();
app.get('/me', (req, res) => {const user = db.get(req.sessionID);res.json({ mySessionId: req.sessionID, me: user ? user : 'anonymous' });
});
const users = [{ name: 'leo', age: 19 }, { name: 'joe', age: 20 }];
app.post('/login', (req, res) => {const { name } = req.body;const user = users.find(u => u.name === name);if (user) {db.set(req.sessionID, user);res.send('ok');} else {res.send('try again');}
});
攻击者可以创建有效的会话 ID 吗?
在本例中,我们使用的是express-session。可以看到我们向express-session中间件传递了一个secret值。这个secret用于签署我们的 cookie 的值。它只是意味着我们确信是我们生成了sessionId。
session示例:
sessionId=s%3AL6j4T8hBwMk1ulJqGoisZbAxUOkOuQqP.x5UxPQEtKrj3sWrIy6S01CQRjAtp4biVs4H2zgqmSs
第一部分:s%3A简单来说:s:这是一个前缀,表明我们的 cookie 会话已签名!
第二部分:L6j4T8hBwMk1ulJqGoisZbAxUOkOuQqP这是我们的sessionId,我们在数据库中使用它来关联数据。
第三部分:x5UxPQEtKrj3sWrIy6S01CQRjAtp4biVs4H2zgqmSs这是签字部分。我们使用我们的secret生成了此文本,因此我们可以确定此 cookie 是由我们生成的。
我们可以简单地重新生成这个标志并检查它是否有效:
const crypto = require('crypto');
const secret = 'secret';
const sessionId = 'L6j4T8hBwMk1ulJqGoisZbAxUOkOuQqP';
const hmac = crypto.createHmac('sha256', secret);
hmac.update(sessionId);
const signature = hmac.digest('base64').replace(/\=+$/, '');
console.log(signature); // x5UxPQEtKrj3sWrIy6S01CQRjAtp4biVs4H2zgqmSs
什么是会话固定?
在会话固定攻击中,攻击者劫持有效的用户会话。我们说过,我们对 cookie 进行签名是为了确保没有人可以劫持其他用户的有效会话。但是,如果攻击者拥有自己的有效会话并尝试将其与另一个用户关联怎么办?在这种情况下,他可以代表受害者采取行动。
当我们没有在 Login 之类的操作上生成新的 sessionIds(唯一标识符)时,就会出现问题。
通过会话固定,攻击者可以劫持有效的用户会话,了解此漏洞并防范它绝对重要。
攻击者如何才能做到这一点?
其中一种情况是攻击者可以物理访问计算机。作为攻击者,我们可以选择一台共享计算机,打开某个已经登录过的网页,然后复制session后发送请求。
sessionId在有些网站在请求中作为 URL 参数传递。在这种情况下,如果攻击者使用其 URL 参数提供登录页面的链接,sessionId则有可能被利用。
如何防止会话固定?
登录时生成新会话
主要解决方案非常简单,通过这样做,始终可以确保不会发生此会话覆盖!
让我们改变代码:
app.post('/login', (req, res) => {const { name } = req.body;req.session.regenerate(err => {if (err) {res.send('error');} else {const user = users.find(u => u.name === name);if (user) {db.set(req.sessionID, user);res.send('ok');} else {res.send('try again');}}});
});
我们可以使用regenerate函数,以便每次有人想要登录时分配一个新的会话。无论我们是否传递会话cookie,它都会生成一个新的会话Id并将其发送到客户端中。
仅使用HTTP Only 的 Cookie
当我们使用HTTP Only时,这意味着只有服务器可以通过Set-Cookie标头设置cookie,而客户端(浏览器JavaScript)无法更改它。所以即使我们的应用存在XSS漏洞,攻击者也无法更改sessionId(cookie)。
防范 XSS
会话固定可以与 XSS 攻击结合使用,从而更加有效,因此如果我们担心会话固定,那么认真对待 XSS 攻击确实有意义。
合理的会话过期时间
会话过期时间应该符合我们的应用程序特定要求,如果我们更关心安全性,那么它应该更短,反之亦然。
正确的注销实施
注销时,我们必须正确销毁现有会话及其与任何数据的关联。否则,这些会话可以在注销后使用。(仅从客户端浏览器中删除 cookie 是不够的!)
相关文章:
什么是会话固定以及如何在 Node.js 中防止它
什么是会话固定以及如何在 Node.js 中防止它 在深入讨论之前,我们需要了解会话是什么以及会话身份验证如何工作。 什么是会话? 正如我们所知,HTTP 请求是无状态的,这意味着当我们发送登录请求时,并且我们有有效的用…...
代码随想录算法训练营第五十二天|300. 最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组
第九章 动态规划part13 300. 最长递增子序列 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数…...
使用 Hugging Face Transformer 微调 BERT
微调 BERT有助于将其语言理解能力扩展到更新的文本领域。BERT 的与众不同之处在于它能够掌握句子的上下文关系,理解每个单词相对于其邻居的含义。我们将使用 Hugging Face Transformers 训练 BERT,还将教 BERT 分析 Arxiv 的摘要并将其分类为 11 个类别之一。 为什么微调 BER…...
Vue原型对象
原型对象 prototype 称为:显示的原型属性,用法:函数.prototype,例如:Vue.prototype __proto__称为:隐式的原型属性,用户:实例.proto,例如:vm.proto 不管如何 …...
向量数据库的分类概况
保存和检索矢量数据的五种方法: 像 Pinecone 这样的纯矢量数据库 全文搜索数据库,例如 ElasticSearch 矢量库,如 Faiss、Annoy 和 Hnswlib 支持矢量的NoSQL 数据库,例如 MongoDB、Cosmos DB 和 Cassandra 支持矢量的SQL 数据库&am…...
工业镜头的类别
工业镜头的类别 按照等效焦距分为: 广角镜头 中焦距镜头 长焦距镜头 广角镜头 等效焦距小于标准镜头(等效焦距为50mm)的镜头。特点是最小工作距离短,景深大,视角大。常常表现为桶形畸变。 中焦距镜头 焦距介于广角镜…...
实验11 SQL互联网业务查询-2
这就是SQL题带给我的自信😕 可能发题解到博客上,主要是写完一遍实在不想看第二遍,太长了,优化都不想优化,看着头疼。 技术栈 – WhiteNights Site 一 USE mydata; #请在此处添加实现代码 ########## Begin #######…...
C++知识点梳理:C++ templates
c模板包括:类模板、类(非模板类和模板类)方法模板、函数模板、别名模板、变量模板。 类模板模板参数列表说明: 1)类定义 仅模板参数列表声明,template<>行。 类名后无需参数说明<>。 2…...
uniapp form表单提交事件手动调用
背景: UI把提交的按钮弄成了图片,之前的button不能用了。 <button form-type"submit">搜索</button> 实现: html: 通过 this.$refs.fd 获取到form的vue对象。手动调用里面的_onSubmit()方法。 methods:…...
Accelerate 0.24.0文档 三:超大模型推理(内存估算、Sharded checkpoints、bitsandbytes量化、分布式推理)
文章目录 一、内存估算1.1 Gradio Demos1.2 The Command 二、使用Accelerate加载超大模型2.1 模型加载的常规流程2.2 加载空模型2.3 分片检查点(Sharded checkpoints)2.4 示例:使用Accelerate推理GPT2-1.5B2.5 device_map 三、bitsandbytes量…...
HackTheBox-Starting Point--Tier 2---Markup
文章目录 一 Markup测试过程1.1 打点1.2 权限获取1.3 权限升级 二 题目 一 Markup测试过程 1.1 打点 1.端口扫描 nmap -A -Pn -sC 10.129.95.1922.访问web网站,登录口爆破发现存在弱口令admin:password 3.抓包,发现请求体是XML格式 4.尝试使…...
android studio导入eclipse项目
网上下载一个老工程,.project文件里有eclipse。 android studio导入eclipse项目 eclipse项目结构 Android studio文件结构 下面是导入步骤: 第一步,打开一个项目。 选择File->New->Import Project 第二步,选择Eclipse项目根…...
如何利用AI实现银行存量客户的营销?
近年来,大数据、人工智能等热门关键字多次被写入中央文件与国务院政府工作报告,目前已上升为国家战略,并将深刻地改变现有行业的游戏规则。 金融行业是当今大数据、人工智能应用最广、最深的领域之一。随着数据仓库和数据科学的发展ÿ…...
springboot327基于Java的医院急诊系统
交流学习: 更多项目: 全网最全的Java成品项目列表 https://docs.qq.com/doc/DUXdsVlhIdVlsemdX 演示 项目功能演示: ————————————————...
Unity3d 导入中文字体转TMPtext asset
外部字体放入unity仓库以后呢,需要把这个字体转成用立体的字体文件才可以被使用! 要想转换的话呢先放入仓库对字体点右键上面有一个Create创建里面有一个TEXT Asset,创建好就可以使用了...
云积万相,焕发电商店铺新活力
数字化时代,电商店铺的运营和营销策略越来越受到重视。如何让店铺在众多的竞争中脱颖而出,吸引更多的顾客,提高销售额,是每个电商品牌都需要思考的问题。云积天赫最近推出的云积万相为电商店铺带来全新的活力和更多的可能性。 …...
字典管理怎么使用,vue3项目使用若依的的字典管理模块
若依框架数据字典的使用_若依数据字典_哈哈水水水水的博客-CSDN博客 【精选】关于数据字典的理解与设计_数据字典怎么设计-CSDN博客 若依的字典值如何使用(超详细图文教程)_若依字典管理_丿BAIKAL巛的博客-CSDN博客 Vue3组合式API:getCurr…...
【汇编】内存中字的存储、用DS和[address]实现字的传送、DS与数据段
文章目录 前言一、内存中字的存储1.1 8086cpu字的概念1.2 16位的字存储在一个16位的寄存器中,如何存储?1.3 字单元 二、用DS和[address]实现字的传送2.1 字的传送是什么意思?2.2 要求原理解决方案:DS和[address]配合8086传送16字节…...
数据分析 - 分散性与变异的量度
全距 - 极差 处理变异性 方差度量 数值与均值的距离,也就是数据的差异性 标准差描述:典型值 和 均值的距离的方法,数据与均值的分散情况...
Neo4j数据库介绍及简单使用
图数据库介绍 图数据库是一种专门设计用于存储和管理图形数据的数据库类型。在图数据库中,数据以图的形式表示,其中节点表示实体,边表示实体之间的关系。这种表示方式非常适合处理具有复杂关系的数据,如社交网络、推荐系统、网络…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...
关于uniapp展示PDF的解决方案
在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项: 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库: npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...
