您的当前位置:首页 >系统运维 >Express-Session:SessionId 机制驱动的一个 Express 会话数据存储库 正文
时间:2025-11-04 22:36:36 来源:网络整理编辑:系统运维
Express 是一个 Node.js 的 Web 框架,提供对外服务器的功能。中间件则是 Express 提供的一种扩展能力的插件机制。express-session 就是 Express 的一个中
Express 是制驱一个 Node.js 的 Web 框架,提供对外服务器的数据功能。中间件则是存储 Express 提供的一种扩展能力的插件机制。
express-session 就是制驱 Express 的一个中间件。使用 sessionId 的数据机制,为用户在网站访问期间,存储提供会话数据的制驱存储支持。
技术实现上,数据express-session 就是存储为每个用户生成唯一的一个 sessionId(默认通过名为 connect.sid 的 cookie 字段)并存储在服务器上。在后续请求往返间,制驱后端通过这个 sessionId 就能拿到之前存储的数据数据,实现用户访问状态的存储记忆。
注意:会话数据的制驱存储往往会借助文件系统或者数据库系统(生产上通常叫缓冲数数据库,比如 redis)等。数据express-session 管数据存储叫 Store,存储默认使用的是内存(MemoryStore),IT技术网不过生产上并不推荐。
图片
express-session 依赖 express,因此使用时需要保证 express 也存在。
复制$ npm install express express-session1.下面是一个简单的使用。
复制var express = require(express) var session = require(express-session) var app = express() app.use(session({ secret: keyboard cat, resave: false, saveUninitialized: true }))1.2.3.4.5.6.7.8.9.10.secret 是必填项,作为生成 sessio ID 的盐值。resave、saveUninitialized 都是选填项,不过由于这 2 个选项的默认值会在未来版本修改,因此官方推荐显式传入。
express-session 是通过中间件方式注入到 express 应用中的。经 express-session 处理后的请求实例 req 都包含一个 .session 属性,我们是通过在 .session 属性上存储信息,实现前后请求会话数据的保存的。
以下,我们将通过 2 个复杂一点的案例来介绍 express-session 的使用。
这里举了 2 个例子,一个是统计用户页面访问次数,源码下载还有一个是用户登录的例子。
我们先亮代码(不是很多)。
复制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)1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.这里我们起了一个监听在 3000 端口的服务器,对访问 /foo、/bar 页面的次数做了统计。
首先express(session({ ... })) 一下,做好会话存储准备,调用后,会在每一次请求(req)添加一个 .session 对象属性页面访问数据存储在 req.session.views 对象属性上,初次访问时是没有这个对象的,就创建({})接下来获取某个访问路径下(req.path)的访问次数(+1),结束用户登录是一个稍微复杂一点的例子,分登录和退出,我们拆开来讲。
首先,我们针对用户登录和未登录状态来区别显示首页内容:
用户已登录状态下,显示用户名、暴露退出入口用户未登录状态下,显示登录表单,登录请求发送至 /login以下是代码实现:
复制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 authenticated function 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)1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.这里我们起了一个监听在 3000 端口的服务器,根据登录状态处理首页展示逻辑。WordPress模板
还是老样子,首先express(session({ ... })) 一下,做好会话存储准备,这一步会在每一次请求(req)添加一个 .session 对象属性先跑第一个 / 路径逻辑,这一步会先经过 isAuthenticated 中间件校验用户登录后,我们会创建一个 req.session.user 属性存储是用户数据,isAuthenticated 是检查这个属性又没有的,有 req.session.user 话,就说明登陆了,展示用户信息(next());没有 req.session.user 的话,说明未登录,则忽略用户信息展示,跳转至下一个路由处理(next(route),也就是第 3 步)经过上一步,到这一步说明用户未登录,我们就发送一个登录表单,让用户填写。登录表单包含 user、pass 字段信息。接下来,我们来看看 /login 页面的处理逻辑。
复制// ... // 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.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29. 为了能正确处理 <form> 表单提交数据,我们使用 express.urlencoded({ extended: false }) 中间件将 form 表单数据收集到 req.body 上我们一上来并没有立即对 req.body.user/req.body.pass 进行校验,而是调用了 req.session.regenerate() 重新生成用户会话 sessionId,这能避免会话固定攻击(session fixation attack)接下来,为了做简单演示,我们没有校验密码,而是直接将提交的用户名存储下来(req.session.user = req.body.user)在重定向会首页之前,我们又调用了 req.session.save() 将新 sessionId 下的 user 信息同步给 Store(默认是缓存,实际生产往往是一个缓存数据库(像 redis))最后,重定到首页,这时候页面就显示登录用户名了再来看看退出登录(/logout)的逻辑。
复制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.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22. 首先,我们将 req.session.user 置为空然后,req.session.save() 将上面的修改同步到 Store接着,通过调用 req.session.regenerate() 重新生成 sessionId,这块跟登录一样,是为了避免会话固定攻击最后,重定到首页,这时候页面就未登录状态下的登录框了express-session 是用来为 express 框架提供会话缓存支持的一个中间件。技术上是通过使用 sessionId 机制提供会话记忆支持的。
本文分别列举了 2 个案例来说明 express-session 的使用:访问次数和用户登录。不过需要注意的是,不管是登录还是退出,都要有一个新生成 sessionId 的过程(req.session.regenerate()),这是为了避免会话固定攻击。
通过激情探索学习(以passion为引导,最大化教程的效果与体验)2025-11-04 22:32
动态壁纸给linux发行版添加活力背景2025-11-04 22:21
教你用n2n在Linux上配置一个非常实用免费的VPN解决方案2025-11-04 22:12
InnoDB 隔离模式对 MySQL 性能的影响2025-11-04 22:00
电脑远程连接出现证书错误的解决方法(如何处理电脑远程连接中的证书错误问题)2025-11-04 21:57
如何为Linux系统中的SSH添加双重认证2025-11-04 21:42
精讲Redis限流:多种方法与生产实践2025-11-04 21:34
6个监控linux系统资源的快速工具2025-11-04 21:30
Pixelbook教程(探索Pixelbook的功能与技巧,体验极致的电脑操作体验)2025-11-04 21:00
Springboot整合Ehcache和Redis实现多级缓存实战案例2025-11-04 20:57
iPhone5s升级iOS8.1的全面指南(了解如何为iPhone5s安装最新的iOS8.1系统)2025-11-04 22:33
12秒“挪走”2500万!以太坊漏洞暴露,麻省理工两学子一手主导闪电窃案,或将面临二十年铁窗生涯2025-11-04 22:05
微服务部署—Docker Compose搭建高可用双机热备MySQL数据库2025-11-04 22:03
如何在Linux命令行下收听网络电台2025-11-04 21:37
三星台式电脑装机教程(简单易懂的三星台式电脑装机教程,助你快速搭建个人工作站)2025-11-04 21:27
中国在线反欺诈市场代表性厂商,瑞数信息再获IDC认可2025-11-04 20:32
浅谈HBase数据结构和系统架构2025-11-04 20:01
SQL还是NoSQL?架构师必备选型技能2025-11-04 19:58
掌握平板电脑4指操作技巧,高效利用设备(简单易学的平板电脑4指操作教程,助您成为高手)2025-11-04 19:57
Atlas 分布式版重磅来袭!2025-11-04 19:56