使用 Express Sessions、Redis 和 Passport 进行 Node.js 会话管理 - 第 1 部分
redis-session-demo 概述
如何运行
它是如何工作的
分支
最近,我着手创建一个演示应用程序,用于我在 纽约 Redis Day 的演讲,该演示应用程序演示了会话管理如何在 Node.js/Express Web 应用中工作,使用 Redis 作为会话存储,并在其基础上添加身份验证功能。理解这些概念以及它们如何协同工作是一回事,但我之前从未真正构建过一个使用所有这些组件的应用程序。
作为初步研究的一部分,我查找了现有的教程或示例,它们可以实现我的目标。我找到了一些不错的 博客 文章 和 教程 ,但没有一个能完全满足我的要求。本教程的第一部分将逐步指导您使用 Node.js 和 Express 构建一个 Web 应用,该应用使用 express-session 和 connect-redis 来帮助用户理解会话管理的工作原理。第二部分将在此基础上进行扩展,使用 Passport 实现身份验证,并探索身份验证和会话如何协同工作。
获取精酿啤酒名称演示应用程序的代码
我们将从一个简单的演示应用开始,一旦它启动并运行,我们将添加会话管理和身份验证。我们首先克隆包含演示应用代码的 GitHub 仓库,然后切换到 beer-demo 分支。
$ git clone https://github.com/jankleinert/redis-session-demo
$ cd redis-session-demo
$ git checkout beer-demo
Enter fullscreen mode
Exit fullscreen mode
让我们尝试运行该应用程序以确保其正常运行。
$ npm install
$ npm run dev
Enter fullscreen mode
Exit fullscreen mode
在浏览器中打开 http://localhost:3000 ,您应该会看到类似这样的内容。
了解演示应用程序
该演示应用使用 express-generator 构建了应用框架。它使用 Pug 作为视图引擎。点击“Pour Another”按钮时,它会向 API 发出请求,该 API 将返回由机器学习生成的精酿啤酒名称。目前,该应用所做的就是这些。
我们将要使用的三个主要文件是 app.js
、 /routes/index.js
和 /views/index.pug
。
我们为什么要关心会话管理?
“会话”是一个含义丰富的术语,根据上下文可能含义迥异。在本教程中,我们讨论的是 Web 应用中的用户会话。您可以将其理解为 Web 应用内由单个用户发起的一系列请求和响应,从用户开始交互到会话结束或会话过期。
为什么我们关心或需要像会话这样的结构?HTTP 是无状态的,因此每个请求和响应对都是独立的。默认情况下,HTTP 不会维护任何状态,服务器也无法从一个请求到另一个请求知道您的身份。会话管理使我们能够为用户会话分配一个标识符,并使用该 ID 来存储与会话相关的状态或数据。这可以是用户是否经过身份验证、购物车中的商品等等——任何在会话期间需要保存的状态。
处理会话管理的方法有多种,但我们将研究一种特定的方法,即将会话数据保存在会话存储中,并且我们将使用 Redis 作为会话存储。
在客户端,Cookie 会存储会话 ID,但不存储任何会话数据。在应用程序的会话存储(本例中为 Redis)中,会话 ID 也会与会话数据一起存储。
向应用程序添加会话信息面板
为了方便直观地了解会话的运行情况,我们将在应用中添加一个会话信息面板。打开 /views/index.pug
并将以下代码添加到文件底部。注意缩进; .session
应与 对齐在同一列 h1
。
.session
p Session Info
if sessionID
p= 'Session ID: ' + sessionID
if sessionExpireTime
p= 'Session expires in ' + Math.round(sessionExpireTime) + ' seconds'
if beersViewed
p= 'Beers viewed in this session: ' + beersViewed
Enter fullscreen mode
Exit fullscreen mode
此面板将显示会话 ID、会话到期前剩余的秒数,以及我们的会话数据:本次会话中已浏览的啤酒名称数量。我们将在 /routes/index.js
后续步骤中指定这些值。
将 express-session 和 connect-redis 添加到 app.js
express-session
是 Express 的会话中间件。它的设置和使用非常简单。市面上有很多 兼容的会话存储 可用于存储会话数据。我们将使用 connect-redis
。首先,安装所需的 npm 模块。
$ npm install --save express-session uuid redis connect-redis
Enter fullscreen mode
Exit fullscreen mode
接下来,打开 app.js
并在现有的 s 下方添加以下代码 require
。 uuid
将用于生成用于我们的会话 ID 的唯一 ID。
const uuid = require('uuid/v4')
const session = require('express-session');
const redis = require('redis');
const redisStore = require('connect-redis')(session);
const redisClient = redis.createClient();
redisClient.on('error', (err) => {
console.log('Redis error: ', err);
});
Enter fullscreen mode
Exit fullscreen mode
在继续下一步之前,请确保您已安装 Redis,并且 Redis 服务器正在运行。如果您需要安装 Redis,可以查看 此文档 。现在我们可以设置会话中间件,并告诉它使用我们的 Redis 存储作为会话存储。在 上方添加此代码 app.use('/', indexRouter);
。
app.use(session({
genid: (req) => {
return uuid()
},
store: new redisStore({ host: 'localhost', port: 6379, client: redisClient }),
name: '_redisDemo',
secret: process.env.SESSION_SECRET,
resave: false,
cookie: { secure: false, maxAge: 60000 }, // Set to secure:false and expire in 1 minute for demo purposes
saveUninitialized: true
}));
Enter fullscreen mode
Exit fullscreen mode
关于这段代码,有几点需要注意。存储会话 ID 的 Cookie 将被命名为“_redisDemo”。我们使用环境变量来设置密钥。下一步,我们将导出该环境变量(您可以随意设置)。为了更容易理解演示应用中的情况,我们将会话有效期设置为 1 分钟。在实际应用中,您应该将 maxAge 设置为更适合您应用的值。在终端中,停止运行 nodemon
,然后运行以下命令。
$ export SESSION_SECRET=some_secret_value_here && npm run dev
Enter fullscreen mode
Exit fullscreen mode
将会话管理代码添加到/routes/index.js
最后一步是添加逻辑,用于跟踪每个会话中啤酒名称的浏览数量,并将会话相关信息传递到会话面板。打开 /routes/index.js
并将现有的代码替换 get
为 post
以下代码。
router.get('/', function(req, res, next) {
var expireTime = req.session.cookie.maxAge / 1000;
res.render('index', { sessionID: req.sessionID, sessionExpireTime: expireTime, beersViewed: req.session.views, beerName: null, beerStyle: null, error: null });
});
router.post('/', function (req, res) {
request('https://www.craftbeernamegenerator.com/api/api.php?type=trained', function (err, response, body) {
if (req.session.views) {
req.session.views++
} else {
req.session.views = 1
}
var expireTime = req.session.cookie.maxAge / 1000;
if(err){
res.render('index', { sessionID: req.sessionID, sessionExpireTime: expireTime, beersViewed: req.session.views, beerName: null, beerStyle: null, error: 'Error, please try again'});
} else {
var beerInfo = JSON.parse(body)
if(beerInfo.status != 200){
res.render('index', { sessionID: req.sessionID, sessionExpireTime: expireTime, beersViewed: req.session.views, beerName: null, beerStyle: null, error: 'Error, please try again'});
} else {
res.render('index', { sessionID: req.sessionID, sessionExpireTime: expireTime, beersViewed: req.session.views, beerName: beerInfo.data.name, beerStyle: beerInfo.data.style, error: null});
}
}
});
});
Enter fullscreen mode
Exit fullscreen mode
我们做了哪些改动?在 中 router.get
,我们添加了 expireTime
,以便计算会话到期前的时间。然后在 中 res.render
,我们传递了一些额外的值:来自 的会话 ID req.sessionID
、我们刚刚计算的到期时间,以及每个会话浏览的啤酒数量(存储为 ) req.session.views
。在会话的第一个页面浏览中,不会有 的值 req.session.views
,但我们的模板知道如何处理这种情况。
在 中 router.post
,我们发出啤酒名称的 API 请求后,如果这是会话中查看的第一个啤酒名称,我们会将其递增 req.session.views
或设置为 1
。然后,与上面看到的类似,我们会在 中传递与会话相关的其他信息 res.render
。
会话管理正在进行中!
一切就绪后,在浏览器中打开 http://localhost:3000 。首次加载时,您应该会看到信息面板显示会话 ID 和会话到期时间。
点击“再来一杯”按钮(请在 60 秒内完成,以免会话过期),您应该会看到会话 ID 保持不变,并且会话中查看的啤酒数量也设置为 1
。如果您在浏览器中打开开发工具并查看 Cookie,您应该会看到一个名为 的 Cookie _redisDemo
,其部分值将包含会话 ID。
最后,如果您启动 redis-cli
然后发出以下命令,其中 YOUR_SESSION_ID
用浏览器中显示的会话 ID 替换,您应该会看到该会话存储在 Redis 中的会话数据,包括视图。
$ redis-cli
$ get "sess:YOUR_SESSION_ID"
Enter fullscreen mode
Exit fullscreen mode
输出应该类似于以下内容:
继续试用一下这个应用,更好地理解会话的工作原理。如果你关闭浏览器,然后快速重新打开,会发生什么?如果你等待超过 60 秒后刷新页面,会发生什么?
至此,希望您对什么是会话管理以及如何使用 express-session
和为 Node.js 应用实现会话管理有了更好的理解 connect-redis
。在第 2 部分中,我们将在本教程的基础上,使用 Passport 为应用添加身份验证功能。
只想要第一部分的代码?点击此处获取:
演示应用程序展示了使用 express-sessions 和 connect-redis 进行 Node.js 应用程序会话管理
redis-session-demo 概述
演示应用展示了如何使用 express-sessions 和 connect-redis 管理 Node.js 应用的会话。最初为 2019 年纽约 Redis Day 制作: https://events.redislabs.com/sessions/life-user-session/
该应用通过 API 查询机器学习生成的精酿啤酒名称,并将其显示在页面上。应用内置一个会话管理面板,用于显示会话 ID、会话到期时间以及该会话中浏览的啤酒名称数量。
在本教程中了解有关其工作原理的更多信息 :
如何运行
确保您已在本地运行 Redis 服务器:
然后克隆这个 repo,运行 npm install,然后在开发模式下运行它:
git clone https://github.com/jankleinert/redis-session-demo
cd redis-session-demo
npm install
export SESSION_SECRET=<some value you choose>
npm run dev
然后在浏览器中访问 http://localhost:3000 。它看起来应该像这样:
它是如何工作的
本演示使用 express-session 进行会话管理,使用 connect-redis 作为会话存储。
分支
主 分支 …
文章来源:https://dev.to/jankleinert/node-js-session-management-using-express-sessions-redis-and-passport-part-1-cja