轻松解决Session-Cookie 鉴权(含坑)附代码

news2024/9/20 20:46:24

Session-Cookie 鉴权

cookie介绍

  • Cookie 存储在客户端,可随意篡改,不安全
  • 有大小限制,最大为 4kb
  • 有数量限制,一般一个浏览器对于一个网站只能存不超过 20 个 Cookie,浏览器一般只允许存放 300个 Cookie
  • Cookie 是不可跨域的,但是一级域名和二级域名是允许共享使用的(靠的是 domain)

session介绍

当浏览器访问服务器并发送第一次请求时,服务器端会创建一个session对象,生成一个类似于 key,value的键值对,然后将key(cookie)返回到浏览器(客户)端,浏览器下次再访问时,携带key(cookie), 找到对应的session(value)。 客户的信息都保存在session中

流程图解

代码实践

技术栈

  • 前端:React
  • 后端:Express + MongoDB

后端部分

1.安装express-session

npm install express-session --save

2.在路由前配置中间件

//配置中间件
app.use(session({secret: "this is Chris Wu", // 可以随便写。 一个 String 类型的字符串,作为服务器端生成 session 的签名name: "session_id" /*保存在本地cookie的一个名字 默认connect.sid可以不设置*/,resave: false /*强制保存 session 即使它并没有变化,。默认为 true。建议设置成 false。*/,saveUninitialized: true, //强制将未初始化的 session 存储。默认值是true建议设置成truecookie: {maxAge: 1000 * 30 * 60/*过期时间*/,secure: false} /*secure https这样的情况才可以访问cookie*/,//设置过期时间比如是30分钟,只要游览页面,30分钟没有操作的话在过期rolling: true, //在每次请求时强行设置 cookie,这将重置 cookie 过期时间(默认:false)})
); 

3.在用户登录接口中设置session req.session.user = username

// 用户登录
const signin = async (req, res, next) => {// 前端传过来的用户名和密码const { username, password } = req.body// 从数据库中查询用户let result = await usersModel.findUser(username) // 验证用户是否是合法用户if (result) {// 设置 sessionreq.session.user = username;res.send({code:1,data:'登陆成功!'});} else {res.send({code:0,data:'用户名或密码错误!'});}
} 

登录成功后,我们可以打开浏览器F12的Application中的Cookies查看,已经生成了一个key为session_id的cookie

4.在需要登录状态下的请求,我们可以通过req.session.user判断,例如一个检查登录的接口

app.get("/check", function (req, res) {//获取sesssionif (req.session.user) {/*获取*/res.send("你好" + req.session.user + "欢迎回来");} else {// 获取不到就返回未登录信息给前端,前端跳到登录页面res.send({errCode: 10001,msg:"未登录"});}
}); 

5.如果想销毁session

 app.get("/logout",function(req,res){//销毁req.session.destroy(function(err){console.log(err);})res.send('退出登录成功');}); 

到这一步后端的鉴权已初步完成

但是设想一下cookie中的maxAge只设置了10秒,用户每一次操作的间隔会很长,再想操作页面时cookie已过期,那又需要重新登录,这样体验感会很差😅😅

6.所以我们可以设置一个全局的中间件,在每次请求时更新session

这个中间件需要放在路由前和session中间件后

app.use((req,res,next)=>{if(req.url.includes('signin')){next();return;}console.log(req.session)if(req.session.user){// 通过new Date()更新sessionreq.session.mydate = new Date();next();}else {res.status(401).send({code:0})}
}) 

7.session可以结合数据库做持久化操作,当服务器挂掉时也不会导致某些客户信息丢失。 我使用的是MongoDB

安装connect-mongo,引入并直接在session中间件中间件中添加如下配置

注意cookie的过期时间和数据库中的过期时间要一致

const MongStore = require('connect-mongo')
//配置中间件
app.use(session({secret: "this is string key", name: "session_id" resave: false saveUninitialized: true, cookie: {maxAge: 1000 * 30 * 60secure: false} rolling: true, store: MongStore.create({mongoUrl:'mongodb://localhost:27017/react_login_session',ttl:1000 * 60 *30})})
); 

到这里后端的工作已全部完成啦

前端部分

1.登录部分

2.axios的封装 由于sessionID保存在cookie中,每次请求会直接带上cookie,使用请求拦截中无需操作

但是如果cookie失效,后端会返回401错误码,所以在请求拦截中需要判断,返回登录页

这里由于不太熟悉React的路由哈哈哈😅😅,所以直接用 window.location.href 跳转登录页了

到这一步前端的工作也完成了

坑!!!

这期间遇到的坑竟然是跨域问题!!

问题

一开始我为了方便就用了npm i cors,直接调用这个中间件解决跨域

请求时session中保存的字段消失了!!

然后我通过打印req.session发现复杂请求会先发一次option预检,再发送真实的请求,这期间session中的字段就会消失

解决

需要在请求头中加上这两行

res.header("Access-Control-Allow-Origin”,"http://locallhost:3000") 不能为*了,必须指定
response.setHeader("Access-Control-Allow-Credentials",true");//是否支持cookie跨域 

当然也可以前端利用webpack中的代理解决跨域,就避免了这个坑

END

  • session-cookie鉴权的操作并不难,可是Session 存储在服务端,增大了服务端的开销,用户量大的时候会大大降低服务器性能,并且非常不安全,Cookie 将数据暴露在浏览器中,增加了数据被盗的风险(容易被 CSRF 等攻击)所以下一篇文章将介绍JWT的操作给大家
  • 希望这篇文章可以帮助到有需要的小伙伴,有问题可以在评论区留言或私信我

最后

最近还整理一份JavaScript与ES的笔记,一共25个重要的知识点,对每个知识点都进行了讲解和分析。能帮你快速掌握JavaScript与ES的相关知识,提升工作效率。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

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

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

相关文章

力扣SQL刷题11

目录标题1194. 锦标赛优胜者--做出来了1225. 报告系统状态的连续日期-勉强1159. 市场分析 II1205. 每月交易II1194. 锦标赛优胜者–做出来了 题型:看题 解答:先处理matches表,整出分数列和players表连接 注意点: union all 时…

【逐步剖C】-番外篇-实用调试技巧

一、 Bug介绍 在正式开始讲解调试技巧之前先介绍一下我们亦敌亦友的Bug。 程序错误,即英文的Bug,也称为缺陷、臭虫,是指在软件运行中因为程序本身有错误而造成的功能不正常、死机、数据丢失、非正常中断等现象。 早期的计算机由于体积非常庞…

2.21、管程

管程就是一个软件模块,里面封装了实现同步,互斥的函数 1、为什么要引入管程 信号量机制存在的问题:编写程序困难、易出错 能不能设计一种机制,让程序员写程序时不需要再关注复杂的 PV 操作,让写代码更轻松呢? 1973年…

使用python从houdini导出arnold材质

先说结果,如果要使用python从houdini导出arnold材质可以使用以下命令 import hou import htoa vops [hou.node("/shop/arnold_vopnet1/")] htoa.material.materialExport(vops,"D:/mat.mtlx")以下是在寻找解决方法的过程中记录的流水账日志 google泛搜索…

MySQL入门篇-MySQL MHA高可用实战

MHA简介 MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司的youshimaton(现就职于Facebook公司)开发,是一套优秀的作为MySQL高可用性环境下故障切换和主从提…

2023软考考哪个证书好?

软考有三个级别(初级,中级和高级),这三个级别分别对应5个方向,下面这张图片呢,可以一目了然,一些小小建议!!!遵循一个原则:首先选专业对口的科目&…

为什么这11道JVM面试题这么重要(附答案)

本文内容整理自 博学谷狂野架构师 运行时数据区都包含什么 虚拟机的基础面试题 程序计数器Java 虚拟机栈本地方法栈Java 堆方法区 程序计数器 程序计数器是线程私有的,并且是JVM中唯一不会溢出的区域,用来保存线程切换时的执行行数 程序计数器&#xff…

算法笔记(三)—— 桶排序及排序总结

堆 逻辑上是一棵完全二叉树(依次遍满或者全满)。 数组可以转为完全二叉树,完全二叉树某结点左孩子(2*i1),右孩子(i*22),父结点((i-1/)2),根节点的父还是自己。 如何将数组转化为堆(大根堆&…

Web自动化测试——selenium篇(一)

文章目录一、环境准备二、Web 自动化测试 Demo三、元素定位常用方法四、元素定位失败可能原因五、测试对象操作六、等待操作七、信息打印在学习 Web 自动化测试的过程中,selenium 是其中的常用工具。除了其开源免费,包含丰富的 API 以外,它还…

基于“PLUS模型+“生态系统服务多情景模拟预测

工业革命以来,社会生产力迅速提高,人类活动频繁,此外人口与日俱增对土地的需求与改造更加强烈,人-地关系日益紧张。此外,土地资源的不合理开发利用更是造成了水土流失、植被退化、水资源短缺、区域气候变化、生物多样性…

windows安装proget实现nuget私有包部署

下载proget 官网 下载地址 免费下载 安装proget 下载完成之后双击安装 选择ProGet 默认选择即可 也可以指定数据库,SQL Server数据库 Server服务器名;Database数据库名;User Id用户名;Password密码 Serverlocalhost;DatabaseProGet2;User Idsa;Passwordxxxx…

浅谈一下前端工作中全流程多层次的四款测试工具

在应届生找工作的时候,我们经常会见到一条招聘要求:要求实习经历。或者 有实习经历者优先。 为什么大部分公司在招聘时,都要求你必须有实习经历? 商业项目与个人项目不同,一段实习经历,能够熟悉公司中成熟…

最接近的三数之和-力扣16-java排序+双指针

一、题目描述给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在恰好一个解。示例 1:输入:nums [-1,2,1,-4], target 1输出&#xff…

Multisim14 安装包及安装教程

Multisim14 安装教程 Multisim14下载地址:Kevin的学习站–安装包下载地址 Multisim14 简介: Multisim 14 是美国国家仪器有限公司(National Instrument,NI)推出的以 Windows 为基础、符合工业标准的、具有 SPICE 最佳仿…

三数之和-力扣15-java排序+双指针

一、题目描述给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k ,同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。注意:答案中不可以包含重复的三元组。…

好用的研发管理看板工具有哪些?10款主流看板管理软件盘点

10大企业看板工具软件:1.软件开发项目看板 PingCode;2.通用看板软件 Worktile;3.开源看板软件 Wekan;4.免费看板软件 Trello;5.个人和小团队的看板软件 Todoist ;6.开源免费看 Kanboard;7.面向个…

想考个PMP证书,怎么报考啊?

先说报名条件: PMP报名条件说难也不难,但也是有条件的,看下面的视频,最难满足的就是题主担心的工作经验,其实这个也并不一定要项目管理经验,年纪合适,一般来说也是可以考的。 PMP考试时间 23年…

微服务实战--高级篇:分布式缓存 Redis

分布式缓存 – 基于Redis集群解决单机Redis存在的问题 单机的Redis存在四大问题: 1.Redis持久化 Redis有两种持久化方案: RDB持久化AOF持久化 1.1.RDB持久化 RDB全称Redis Database Backup file(Redis数据备份文件)&#xf…

数据结构 - 优先级队列(堆)

文章目录前言1.介绍优先级队列2. 认识堆3. 实现优先级队列3.1 了解优先级队列的构造方法:3.2 使用优先级队列解决问题:总结前言 本篇PriorityQueue优先级队列的介绍其底层是堆,关于堆的认识,使用优先级队列能解决的一些问题&…

day12_Django的基本操作

文章目录创建django项目项目-各个文件的含义app-各个文件的含义MVT运行,查看是否创建项目框架成功ORM迁移->在数据库中形成对应的 表通过类名 对象的方法完成数据库的增删查改操作通过模型类(shell)的方法操作数据表后台管理进入后台http:…