一文带你彻底搞懂Session 的工作原理

这两天有好多个小伙伴去面试都被问到session和token相关的问题,那今天婧婧姐就跟大家聊聊session,主要从什么是session,session的工作原理,NodeJS实现session,session的优缺点讲。看完这篇文章,我相信对于session 相关的问题就会迎刃而解啦!

前言

什么是Session呢?

session 字面含义就是会话,主要用于客户端和数据交互做身份验证的。

由于 HTTP 是无状态协议,客户端和服务端数据交互,服务端并不知道客户端是否是登录状态,不知道是客户端哪个用户来请求的数据,为了保持客户端和服务端之间的联系,才有了session的出现,session就是用于在服务端保存用户状态的方式,通常用来保存用户的登录状态。

Session的工作原理

1.Session如何存储用户状态

session以 key=value 的格式保存在服务端,通常是保存在内存中,当然也可以保存在文件或者数据库等等,保存的这个数据称之为session对象,每一个session对象都会存在一个sessionid,客户端和服务端就是通过sessionid来关联的。

2.Session的工作流程

1.客户端向服务端 发送登录HTTP请求,如果这个用户首次访问服务器的时候,服务器为这个用户单独创建一个 Session 对象,并分配一个新的 SessionID,此时 SessionID 通过 cookie 保存在客户端 。

2.客户端之后的每一次HTTP请求,cookie中sessionid都会随着cookie传递到服务端,服务端就根据传递过来的sessionid对用于进行身份的验证。

NodeJS实现Session

NodeJS 也有多种方法生成session对象,婧婧姐今天就使用express-session 来带大家实现session验证吧!

1.安装

css 复制代码
npm install express-session --save

2.导入

ini 复制代码
// index.jsconst express=require("express");const session = require('express-session')

3.配置Session参数

yaml 复制代码
// index.jslet sessionOption = session({   // cookie名字 也就是 cookie中的key   name: "AilixUserSystem",   // 密钥:服务器生成的session的签名   secret: "iahsiuhaishia666sasas",   cookie: {        // 过期时间:一个小时过期       maxAge: 1000 * 60 * 60,  },   // 重新设置session后会重新计算过期时间   rolling: true //每一次访问session过期时间都会重新更新。   // 为true时表示一开始访问网站就生成cookie,不过生成的这个cookie是无效的,相当于是没有激活   saveUninitialized: true,})

在session(option)中对session进行设置,它的主要参数是:

  • name :cookie的名字(原属性名为 key)。(默认:'connect.sid')

  • store :session存储实例

  • secret :用它来对session cookie签名,防止篡改

  • cookie :session cookie设置 (默认:{ path: '/', httpOnly: true,secure: false, maxAge: null })

  • genid :生成新session ID的函数 (默认使用uid2库)

  • rolling :在每次请求时强行设置cookie,这将重置cookie过期时间(默认:false)

  • resave :强制保存session即使它并没有变化 (默认:true, 建议设为:false)

  • proxy :当设置了secure cookies(通过"x-forwarded-proto" header )时信任反向代理。当设定为true时,"x-forwarded-proto" header 将被使用。当设定为false时,所有headers将被忽略。当该属性没有被设定时,将使用Express的trust proxy。

  • saveUninitialized :强制将未初始化的session存储。当新建了一个session且未设定属性或值时,它就处于未初始化状态。在设定一个cookie前,这对于登录验证,减轻服务端存储压力,权限控制是有帮助的。(默认:true)

  • unset :控制req.session是否取消(例如通过 delete,或者将它的值设置为null)。这可以使session保持存储状态但忽略修改或删除的请求(默认:keep)

4.使用配置的Session

session() 是NodeJS中的一个中间件,直接在app.use()中使用即可。

配置 app.use( sessionOption )之后,所有的请求对象中(req)都会存在 session 属性。

arduino 复制代码
// index.jsapp.use(sessionOption)

5.登录成功,用Session对象存储用户信息,表示登录成功状态

sql 复制代码
app.post("/login",async (req, res) => {let {username,password} = req.body;// 去数据库中查询是有该用户存在   lete data = await query(`select * from user where username='${username}' and password='${password}';`)if (data.length == 0) {  res.send({ msg: "登录失败" });  return;}   // 登录成功 把用户信息设置到session对象中req.session.userInfo = "用户相关信息";req.session.isLogin = true;res.send({ msg: "登录成功" });});

会自动把 sessionid 设置到 cookie 中。

6.验证Session

每次发送请求都会把 cookie 中 session 信息携带在请求头中的 cookie 传递给 后端。

后端数据中直接通过 req.session 来获取即可,如果获取不到对应的信息 则表示不存在该 session 或者 该 session 已经过期。

bash 复制代码
server.get("/user", (req, res) => { //获取session中的userInfo信息 let info = req.session.userInfo if(!info){     res.send({msg:'未登录'});     return}   res.send('返回正常的数据')});

7.设置白名单

什么是白名单:即不需要做用户验证的接口。

一个网站中不是所有的数据接口都必须验证用户是否登录,很多数据接口为未登录的情况下也是可以正常请求,那么这一类型的数据接口 就可以设置为白名单。

比如:电商网站,商品列表就不需要登录也可以请求。

我们可以在所有的接口之前对session进行验证,也可以称之为session拦截。

bash 复制代码
// index.js// 设置白名单,以数组形式存储白名单接口let white = ['/list','/details']// 拦截session 进行验证app.use((req,res,next)=>{   // req.url 获取请求路径   if(white.includes(req.url)){       next();       return  }   let info = req.session.userInfo 获取session中的userInfo信息if(!info){    res.send({msg:'未登录'});    return}   next();})// /user 不需要再验证,因为已经统一验证过了server.get("/user", (req, res) => {   res.send('返回正常的数据')});

8.销毁Session

项目中都会存在退出登录的功能,客户端界面功能,很简单,给退出登录按钮绑定一个点击事件,把客户端的登录状态修改为未登录。

那么服务端如何去对用户的由登录状态改变为未登录的状态呢,其中session的存储的状态是 销毁该用户的session对象即可。

lua 复制代码
// index.jsapp.use('/loginOut',function(req,res){   //注销session   req.session.destroy(function(err){       res.send("退出登录!"+err);  });});

Session的优缺点

优点

一个技术既然能被使用,肯定是有它一定的优点,所以我们先从session的优点说起。

  • 相比传统的cookie存储所有用户信息来讲,session的数据存储服务器端,用户数据更安全。

  • 每次请求不需要在请求体或者请求接口中携带用户信息给服务端。

缺点

事务都是两面性的,有优点也会存在一些缺点,那我们也聊聊session的缺点吧。

  • session都是保存在服务端的内存中,而随着认证用户的增多,服务端的开销会明显增大。

  • cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。

  • 多服务器请求session不能实现共享问题,session只适用一个所有数据都在同一个服务器请求,因为提供登录的数据接口的服务器才会有session信息。

  • 跨域设置问题,sessionid会直接设置在cookie中,如果客户端和服务端不是同一个服务器,cookie设置会存在跨域问题。

**注意点:**虽然在配置session的时候可以设置session的过期时间,但是如果你重新启动了服务端的服务器,那么之前的session对象都会被清空,必须得重新登录生成session哦。

希望对大家有所帮助吧!,token下期见,Bye~~

相关推荐
轻口味16 分钟前
【每日学点鸿蒙知识】AVCodec、SmartPerf工具、web组件加载、监听键盘的显示隐藏、Asset Store Kit
前端·华为·harmonyos
alikami18 分钟前
【若依】用 post 请求传 json 格式的数据下载文件
前端·javascript·json
吃杠碰小鸡1 小时前
lodash常用函数
前端·javascript
emoji1111111 小时前
前端对页面数据进行缓存
开发语言·前端·javascript
泰伦闲鱼1 小时前
nestjs:GET REQUEST 缓存问题
服务器·前端·缓存·node.js·nestjs
m0_748250031 小时前
Web 第一次作业 初探html 使用VSCode工具开发
前端·html
一个处女座的程序猿O(∩_∩)O1 小时前
vue3 如何使用 mounted
前端·javascript·vue.js
m0_748235951 小时前
web复习(三)
前端
AiFlutter1 小时前
Flutter-底部分享弹窗(showModalBottomSheet)
java·前端·flutter
麦兜*1 小时前
轮播图带详情插件、uniApp插件
前端·javascript·uni-app·vue