这两天有好多个小伙伴去面试都被问到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~~