前言
随着前端技术的不断发展,越来越多的应用程序开始采用分布式系统架构来提高质量和可用性。JWT 作为一种轻量、快速且可靠的认证机制,已经广泛应用于这些分布式应用中。而 Fastify 作为一个基于 Node.js 平台的高效开发工具,正依托其优秀的性能和可扩展性,逐步成为前端领域的人气工具之一。那么,在这篇文章中,我们将探讨 Fastify 和 JWT 的整合及其使用,并提供一些可供参考的示例代码。
什么是 Fastify?
Fastify 是基于 Node.js 平台的一个高效、低延迟的 Web 框架。它同时具备了优秀的性能和可扩展性,因此,在 Node.js 社区中受到了极高的评价。
特点:
快速:Fastify 在请求和响应处理方面极其快速,它体积小、效率高、代码简单易于维护。
可扩展:开发人员可以轻松地通过插件和中间件来扩展 Fastify 的功能。
现代化:Fastify 采用了 ES2017 的语法,并支持异步、await、promise 等语法特性,因此代码更加易读、简明。
什么是 JWT?
JWT(JSON Web Token)是一种用于认证和授权的标准化 JSON 编码的 token,它由三部分组成:header、payload 和 signature。
header 包含了 token 的类型以及所使用的加密算法。
payload 包含了包含用户信息(例如用户 ID、用户类型等)的 JSON 对象。
signature 是将 header 和 payload 连接在一起并使用密钥进行加密后的结果。
JWT 不需要在服务器端保存任何信息,因此它可以轻松地跨服务器或跨平台使用。
如何整合 Fastify 和 JWT?
安装依赖包
在使用 Fastify 和 JWT 之前,我们需要先通过 npm 安装相应的依赖包:
npm i fastify fastify-jwt
使用 JWT 插件
在 Fastify 中,我们可以通过引入 fastify-jwt 插件来实现 JWT 的功能。这一插件提供了 JWT 在 Fastify 中的实现,并提供了相关的 API 和钩子函数。
在 app.js 中添加以下代码来启用 JWT 插件:
const fastify = require('fastify')() fastify .register(require('fastify-jwt'), { secret: 'supersecret' })
在这里,我们通过调用 fastify-jwt 模块来启用 JWT 插件,并指定密钥为 'supersecret'。
添加路由
为了使用 JWT 来保护我们的路由,我们需要在路由配置中使用一些中间件。如下所示:
fastify.route({ method: 'GET', url: '/protected', preHandler: fastify.auth([fastify.verifyJWT]), handler: (request, reply) => { reply.send({ msg: 'Hello, JWT!' }) } })
这里我们定义了一个受保护的路由 '/protected',并使用了 fastify.auth() 函数来配置中间件。这里我们使用了 fastify-jwt 插件中提供的 fastify.verifyJWT 中间件来验证 JWT。如果验证成功,代码就会向客户端发送 'Hello, JWT!'。
我们也可以为不同的路由配置不同的中间件,如下所示:
fastify.route({ method: 'GET', url: '/protected', preHandler: [ fastify.auth([fastify.verifyJWT]), async (req, reply, done) => { // ... add your async logic here ... done() // pass control to the next preHandler }, ], handler: (request, reply) => { reply.send({ msg: 'Hello, JWT!' }) } })
在这里,我们为 '/protected' 路由配置了两个中间件,其中一个是 fastify-jwt 提供的中间件,另一个则是一个 Promise/A+ 模型的中间件函数(async 函数)。这个 Promise 函数会在 fastify-jwt 中间件之后执行,因此可以在这里对请求进行一些异步处理。
如果您需要配置不受保护的路由,则可以像这样设置:
fastify.route({ method: 'GET', url: '/', handler: (request, reply) => { reply.send({ msg: 'Hello, World!' }) } })
注册用户及发行 token
为了使用 JWT,我们需要为每个用户提供一个唯一的 token。在 Fastify 中,我们可以使用 fastify-jwt 插件提供的 sign() 方法来创建 token。例如:
fastify.post('/login', async (request, reply) => { const { username, password } = request.body const user = await User.findOne({ username }) if (!user) { throw new Error('User not found') } if (password !== user.password) { throw new Error('Password incorrect') } const token = fastify.jwt.sign({ username }) reply.send({ token }) })
在这里,我们使用了 post 方法来处理用户的登录请求。我们根据用户名从数据库中查询对应的用户信息。如果用户不存在或者密码错误,我们就直接抛出错误。
然后,我们使用 fastify.jwt.sign() 来签发一个 token,其中包含了用户的用户名信息。
最后,我们将 token 作为响应体中的一部分返回给客户端。
验证 token
在 Fastify 中,我们可以使用 verifyJWT() 中间件来验证请求的 token。例如:
fastify.route({ method: 'GET', url: '/protected', preHandler: fastify.auth([fastify.verifyJWT]), handler: (request, reply) => { const username = request.user.username reply.send({ msg: `Hello, ${username}!` }) } })
在这里,我们使用 fastify.auth() 中间件来指定 verifyJWT() 中间件作为 preHandler,以确保只有验证通过的 token 才能访问该路由。fastify-jwt 插件会自动将验证通过的 token 信息存储在 request.user 对象中,并以此来验证对该路由的访问。
总结
通过本文的阐述,您应该已经了解了如何在 Fastify 中使用 JWT。其中,我们在配置路由和中间件时使用了 fastify.verifyJWT 中间件来验证 token 的有效性,同时使用了 fastify-jwt 插件提供的功能来签发和解密 token。希望本文能够为您在实际开发中的工作提供一定的指导和参考意义。
示例代码
const fastify = require('fastify')() const mongoose = require('mongoose') mongoose.connect(process.env.MONGODB_URI) const User = require('./models/User') fastify .register(require('fastify-jwt'), { secret: 'supersecret' }) fastify.route({ method: 'GET', url: '/', handler: (request, reply) => { reply.send({ msg: 'Hello, World!' }) } }) fastify.route({ method: 'GET', url: '/protected', preHandler: fastify.auth([fastify.verifyJWT]), handler: (request, reply) => { const username = request.user.username reply.send({ msg: `Hello, ${username}!` }) } }) fastify.post('/login', async (request, reply) => { const { username, password } = request.body const user = await User.findOne({ username }) if (!user) { throw new Error('User not found') } if (password !== user.password) { throw new Error('Password incorrect') } const token = fastify.jwt.sign({ username }) reply.send({ token }) }) fastify.listen(process.env.PORT || 3000, (err, address) => { if (err) throw err console.log(`Server listening on ${address}`) })
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65aa71a1add4f0e0ff40bc0c