当前位置:首页 > 科技  > 软件

Express-Session:SessionId 机制驱动的一个 Express 会话数据存储库

来源: 责编: 时间:2023-12-12 17:01:50 314观看
导读Express 是一个 Node.js 的 Web 框架,提供对外服务器的功能。中间件则是 Express 提供的一种扩展能力的插件机制。express-session 就是 Express 的一个中间件。使用 sessionId 的机制,为用户在网站访问期间,提供会话数

Express 是一个 Node.js 的 Web 框架,提供对外服务器的功能。中间件则是 Express 提供的一种扩展能力的插件机制。Cmf28资讯网——每日最新资讯28at.com

express-session 就是 Express 的一个中间件。使用 sessionId 的机制,为用户在网站访问期间,提供会话数据的存储支持。Cmf28资讯网——每日最新资讯28at.com

技术实现上,express-session 就是为每个用户生成唯一的一个 sessionId(默认通过名为 connect.sid 的 cookie 字段)并存储在服务器上。在后续请求往返间,后端通过这个 sessionId 就能拿到之前存储的数据,实现用户访问状态的记忆。Cmf28资讯网——每日最新资讯28at.com

注意:会话数据的存储往往会借助文件系统或者数据库系统(生产上通常叫缓冲数数据库,比如 redis)等。express-session 管数据存储叫 Store,默认使用的是内存(MemoryStore),不过生产上并不推荐。Cmf28资讯网——每日最新资讯28at.com

图片图片Cmf28资讯网——每日最新资讯28at.com

安装 & 简单使用

express-session 依赖 express,因此使用时需要保证 express 也存在。Cmf28资讯网——每日最新资讯28at.com

$ npm install express express-session

下面是一个简单的使用。Cmf28资讯网——每日最新资讯28at.com

var express = require('express')var session = require('express-session')var app = express()app.use(session({  secret: 'keyboard cat',  resave: false,  saveUninitialized: true}))

secret 是必填项,作为生成 sessio ID  的盐值。resave、saveUninitialized 都是选填项,不过由于这 2 个选项的默认值会在未来版本修改,因此官方推荐显式传入。Cmf28资讯网——每日最新资讯28at.com

express-session 是通过中间件方式注入到 express 应用中的。经 express-session 处理后的请求实例 req 都包含一个 .session 属性,我们是通过在 .session 属性上存储信息,实现前后请求会话数据的保存的。Cmf28资讯网——每日最新资讯28at.com

以下,我们将通过 2 个复杂一点的案例来介绍 express-session 的使用。Cmf28资讯网——每日最新资讯28at.com

案例介绍

这里举了 2 个例子,一个是统计用户页面访问次数,还有一个是用户登录的例子。Cmf28资讯网——每日最新资讯28at.com

统计页面访问次数

我们先亮代码(不是很多)。Cmf28资讯网——每日最新资讯28at.com

var express = require('express')var session = require('express-session')var app = express()// 1)app.use(session({  secret: 'keyboard cat',  resave: false,  saveUninitialized: true}))app.use(function (req, res, next) {  // 2)  if (!req.session.views) {    req.session.views = {}  }  // get the url pathname  var pathname = req.path  // 3)  // count the views  req.session.views[pathname] = (req.session.views[pathname] || 0) + 1  next()})app.get('/foo', function (req, res, next) {  res.send('you viewed this page ' + req.session.views['/foo'] + ' times')})app.get('/bar', function (req, res, next) {  res.send('you viewed this page ' + req.session.views['/bar'] + ' times')})app.listen(3000)

这里我们起了一个监听在 3000 端口的服务器,对访问 /foo、/bar 页面的次数做了统计。Cmf28资讯网——每日最新资讯28at.com

  1. 首先express(session({ ... })) 一下,做好会话存储准备,调用后,会在每一次请求(req)添加一个 .session 对象属性
  2. 页面访问数据存储在 req.session.views 对象属性上,初次访问时是没有这个对象的,就创建({})
  3. 接下来获取某个访问路径下(req.path)的访问次数(+1),结束

用户登录

用户登录是一个稍微复杂一点的例子,分登录和退出,我们拆开来讲。Cmf28资讯网——每日最新资讯28at.com

首先,我们针对用户登录和未登录状态来区别显示首页内容:Cmf28资讯网——每日最新资讯28at.com

  • 用户已登录状态下,显示用户名、暴露退出入口
  • 用户未登录状态下,显示登录表单,登录请求发送至 /login

以下是代码实现:Cmf28资讯网——每日最新资讯28at.com

var escapeHtml = require('escape-html')var express = require('express')var session = require('express-session')var app = express()// 1)app.use(session({  secret: 'keyboard cat',  resave: false,  saveUninitialized: true}))// 2.1) middleware to test if authenticatedfunction isAuthenticated (req, res, next) {  if (req.session.user) next()  else next('route')}// 2)app.get('/', isAuthenticated, function (req, res) {  // this is only called when there is an authentication user due to isAuthenticated  res.send('hello, ' + escapeHtml(req.session.user) + '!' +    ' <a href="/logout">Logout</a>')})// 3)app.get('/', function (req, res) {  res.send('<form actinotallow="/login" method="post">' +    'Username: <input name="user"><br>' +    'Password: <input name="pass" type="password"><br>' +    '<input type="submit" text="Login"></form>')})// ...app.listen(3000)

这里我们起了一个监听在 3000 端口的服务器,根据登录状态处理首页展示逻辑。Cmf28资讯网——每日最新资讯28at.com

  1. 还是老样子,首先express(session({ ... })) 一下,做好会话存储准备,这一步会在每一次请求(req)添加一个 .session 对象属性
  2. 先跑第一个 / 路径逻辑,这一步会先经过 isAuthenticated 中间件校验
  1. 用户登录后,我们会创建一个 req.session.user 属性存储是用户数据,isAuthenticated 是检查这个属性又没有的,有  req.session.user 话,就说明登陆了,展示用户信息(next());没有  req.session.user 的话,说明未登录,则忽略用户信息展示,跳转至下一个路由处理(next('route'),也就是第 3 步)
  1. 经过上一步,到这一步说明用户未登录,我们就发送一个登录表单,让用户填写。登录表单包含 user、pass 字段信息。

接下来,我们来看看 /login 页面的处理逻辑。Cmf28资讯网——每日最新资讯28at.com

// ...// 1)app.post('/login', express.urlencoded({ extended: false }), function (req, res) {  // login logic to validate req.body.user and req.body.pass  // would be implemented here. for this example any combo works  // regenerate the session, which is good practice to help  // guard against forms of session fixation  // 1)  req.session.regenerate(function (err) {    if (err) next(err)    // store user information in session, typically a user id    // 2)    req.session.user = req.body.user    // save the session before redirection to ensure page    // load does not happen before session is saved    // 3)    req.session.save(function (err) {      if (err) return next(err)      // 4)      res.redirect('/')    })  })})// ...
  1. 为了能正确处理 <form> 表单提交数据,我们使用 express.urlencoded({ extended: false }) 中间件将 form 表单数据收集到 req.body 上
  2. 我们一上来并没有立即对 req.body.user/req.body.pass 进行校验,而是调用了 req.session.regenerate() 重新生成用户会话 sessionId,这能避免会话固定攻击(session fixation attack)
  3. 接下来,为了做简单演示,我们没有校验密码,而是直接将提交的用户名存储下来(req.session.user = req.body.user)
  4. 在重定向会首页之前,我们又调用了 req.session.save() 将新 sessionId 下的 user 信息同步给 Store(默认是缓存,实际生产往往是一个缓存数据库(像 redis))
  5. 最后,重定到首页,这时候页面就显示登录用户名了

再来看看退出登录(/logout)的逻辑。Cmf28资讯网——每日最新资讯28at.com

app.get('/logout', function (req, res, next) {  // logout logic  // clear the user from the session object and save.  // this will ensure that re-using the old sessionId  // does not have a logged in user  // 1)  req.session.user = null  // 2)  req.session.save(function (err) {    if (err) next(err)    // regenerate the session, which is good practice to help    // guard against forms of session fixation    // 3)    req.session.regenerate(function (err) {      if (err) next(err)      // 4)      res.redirect('/')    })  })})
  1. 首先,我们将 req.session.user 置为空
  2. 然后,req.session.save() 将上面的修改同步到 Store
  3. 接着,通过调用  req.session.regenerate() 重新生成 sessionId,这块跟登录一样,是为了避免会话固定攻击
  4. 最后,重定到首页,这时候页面就未登录状态下的登录框了

总结

express-session 是用来为 express 框架提供会话缓存支持的一个中间件。技术上是通过使用 sessionId 机制提供会话记忆支持的。Cmf28资讯网——每日最新资讯28at.com

本文分别列举了 2 个案例来说明 express-session 的使用:访问次数和用户登录。不过需要注意的是,不管是登录还是退出,都要有一个新生成 sessionId 的过程(req.session.regenerate()),这是为了避免会话固定攻击。Cmf28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-43315-0.htmlExpress-Session:SessionId 机制驱动的一个 Express 会话数据存储库

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: WebStorm 2023.3 来了,更好用,更智能!

下一篇: 前端发起异步请求受浏览器同源策略限制,导致跨域问题

标签:
  • 热门焦点
  • 7月安卓手机性价比榜:努比亚+红魔两款新机入榜

    7月登场的新机有努比亚Z50S Pro和红魔8S Pro,除了三星之外目前唯二的两款搭载超频版骁龙8Gen2处理器的产品,而且努比亚和红魔也一贯有着不错的性价比,所以在本次的性价比榜单
  • 线程通讯的三种方法!通俗易懂

    线程通信是指多个线程之间通过某种机制进行协调和交互,例如,线程等待和通知机制就是线程通讯的主要手段之一。 在 Java 中,线程等待和通知的实现手段有以下几种方式:Object 类下
  • SpringBoot中使用Cache提升接口性能详解

    环境:springboot2.3.12.RELEASE + JSR107 + Ehcache + JPASpring 框架从 3.1 开始,对 Spring 应用程序提供了透明式添加缓存的支持。和事务支持一样,抽象缓存允许一致地使用各
  • 从零到英雄:高并发与性能优化的神奇之旅

    作者 | 波哥审校 | 重楼作为公司的架构师或者程序员,你是否曾经为公司的系统在面对高并发和性能瓶颈时感到手足无措或者焦头烂额呢?笔者在出道那会为此是吃尽了苦头的,不过也得
  • 一文搞定Java NIO,以及各种奇葩流

    大家好,我是哪吒。很多朋友问我,如何才能学好IO流,对各种流的概念,云里雾里的,不求甚解。用到的时候,现百度,功能虽然实现了,但是为什么用这个?不知道。更别说效率问题了~下次再遇到,
  • JVM优化:实战OutOfMemoryError异常

    一、Java堆溢出堆内存中主要存放对象、数组等,只要不断地创建这些对象,并且保证 GC Roots 到对象之间有可达路径来避免垃 圾收集回收机制清除这些对象,当这些对象所占空间超过
  • 到手价3099元起!iQOO Neo8 Pro今日首销:安卓性能最强旗舰

    5月23日,iQOO如期举行了新品发布会,全新的iQOO Neo8系列也正式与大家见面,包含iQOO Neo8和iQOO Neo8 Pro两个版本,其中标准版搭载高通骁龙8+,而Pro版更
  • 苹果MacBook Pro 2021测试:仍不支持平滑滚动

    据10月30日9to5 Mac 消息报道,苹果新的 14 英寸和 16 英寸 MacBook Pro 2021 上市后获得了不错的评价,亮点包括行业领先的性能,令人印象深刻的电池续航,精美丰
  • “买真退假” 这种“羊毛”不能薅

    □ 法治日报 记者 王春   □ 本报通讯员 胡佳丽  2020年初,还在上大学的小东加入了一个大学生兼职QQ群。群主&ldquo;七王&rdquo;在群里介绍一些刷单赚
Top