Fastify 是一个基于 Node.js 的快速和低开销的 Web 框架,它被设计为构建高效的 RESTful API。在实际开发中,我们通常需要为我们的应用程序添加访问控制和身份验证功能,以确保只有经过授权的用户才能访问我们的 API。在本文中,我们将介绍如何为 Fastify 实现访问控制和身份验证。
访问控制
访问控制是一种安全机制,用于限制对系统或资源的访问。在 Fastify 中,我们可以使用插件来实现访问控制。
fastify-auth 插件
fastify-auth 是一个 Fastify 插件,它提供了一种简单的方法来实现基于 JSON Web Token(JWT)的身份验证和访问控制。
首先,我们需要安装 fastify-auth 插件:
npm install fastify-auth
然后,我们可以在 Fastify 应用程序中注册 fastify-auth 插件:
const fastify = require('fastify')()
fastify.register(require('fastify-auth'))现在,我们可以使用 fastify.auth() 方法来定义我们的路由需要进行身份验证:
fastify.get('/private', { preValidation: fastify.auth([fastify.verifyJWT]) }, async (request, reply) => {
return { secret: 'This is a secret message' }
})在上面的代码中,我们使用 fastify.auth() 方法定义了一个需要进行身份验证的路由。该路由的 preValidation 选项指定了需要使用的验证函数。
fastify-jwt 插件
fastify-jwt 是一个 Fastify 插件,它提供了一种简单的方法来生成和验证 JSON Web Token(JWT)。
首先,我们需要安装 fastify-jwt 插件:
npm install fastify-jwt
然后,我们可以在 Fastify 应用程序中注册 fastify-jwt 插件:
const fastify = require('fastify')()
fastify.register(require('fastify-jwt'), {
secret: 'supersecret'
})在上面的代码中,我们使用 fastify-jwt 插件设置了一个密钥。该密钥将用于生成和验证 JWT。
现在,我们可以使用 fastify.jwt.sign() 方法生成 JWT:
const token = fastify.jwt.sign({ username: 'alice' })在上面的代码中,我们使用 fastify.jwt.sign() 方法生成了一个包含用户名“alice”的 JWT。
然后,我们可以在需要进行身份验证的路由中使用 fastify.verifyJWT() 方法来验证 JWT:
fastify.get('/private', { preValidation: fastify.auth([fastify.verifyJWT]) }, async (request, reply) => {
const decoded = await request.jwtVerify()
return { secret: 'This is a secret message', username: decoded.username }
})在上面的代码中,我们使用 fastify.verifyJWT() 方法验证了 JWT,并从 JWT 中提取了用户名。
身份验证
身份验证是一种安全机制,用于确认用户的身份。在 Fastify 中,我们可以使用插件来实现身份验证。
fastify-auth 插件
fastify-auth 插件不仅可以用于访问控制,还可以用于身份验证。
首先,我们需要安装 fastify-auth 插件(如果还没有安装):
npm install fastify-auth
然后,我们可以在 Fastify 应用程序中注册 fastify-auth 插件:
const fastify = require('fastify')()
fastify.register(require('fastify-auth'))现在,我们可以使用 fastify.decorate() 方法来添加一个验证函数:
// www.javascriptcn.com code example
fastify.decorate('authenticate', async function (request, reply) {
const header = request.headers.authorization
if (!header) throw new Error('Missing authorization header')
const [scheme, token] = header.split(' ')
if (scheme !== 'Bearer') throw new Error('Invalid authorization scheme')
try {
const decoded = await fastify.jwt.verify(token)
request.user = decoded
} catch (err) {
throw new Error('Invalid token')
}
})在上面的代码中,我们使用 fastify.decorate() 方法添加了一个名为 authenticate 的验证函数。该函数从请求头中提取 JWT,并验证 JWT 的有效性。
现在,我们可以在需要进行身份验证的路由中使用 fastify.authenticate() 方法来调用验证函数:
fastify.get('/private', { preValidation: fastify.authenticate }, async (request, reply) => {
return { secret: 'This is a secret message', username: request.user.username }
})在上面的代码中,我们使用 fastify.authenticate() 方法调用了 authenticate 验证函数,并从 JWT 中提取了用户名。
示例代码
下面是一个完整的示例代码,演示了如何为 Fastify 实现访问控制和身份验证:
// www.javascriptcn.com code example
const fastify = require('fastify')()
fastify.register(require('fastify-auth'))
fastify.register(require('fastify-jwt'), {
secret: 'supersecret'
})
fastify.decorate('authenticate', async function (request, reply) {
const header = request.headers.authorization
if (!header) throw new Error('Missing authorization header')
const [scheme, token] = header.split(' ')
if (scheme !== 'Bearer') throw new Error('Invalid authorization scheme')
try {
const decoded = await fastify.jwt.verify(token)
request.user = decoded
} catch (err) {
throw new Error('Invalid token')
}
})
fastify.get('/public', async (request, reply) => {
return { message: 'This is a public message' }
})
fastify.get('/private', { preValidation: fastify.authenticate }, async (request, reply) => {
return { secret: 'This is a secret message', username: request.user.username }
})
fastify.listen(3000, (err) => {
if (err) {
console.error(err)
process.exit(1)
}
console.log('Server listening on port 3000')
})在上面的代码中,我们定义了两个路由:/public 和 /private。/public 路由是公共路由,不需要进行身份验证。/private 路由是需要进行身份验证的私有路由。
我们首先使用 fastify-auth 和 fastify-jwt 插件注册了 Fastify 应用程序。然后,我们使用 fastify.decorate() 方法添加了一个名为 authenticate 的验证函数。最后,我们定义了两个路由,并在 /private 路由中使用了 authenticate 验证函数。
现在,您可以运行上面的代码,并使用 curl 命令测试 API:
# 发送 GET 请求到 /public 路由 curl http://localhost:3000/public # 发送 GET 请求到 /private 路由(未经身份验证) curl http://localhost:3000/private # 发送 GET 请求到 /private 路由(经过身份验证) curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFsaWNlIiwiaWF0IjoxNTE2MjM5MDIyfQ.MvN0oWd7bN9-9y1d3sZz8W1KpJZwGJZ0oYvz8gRrT-4" http://localhost:3000/private
如果您发送未经身份验证的 GET 请求到 /private 路由,您将得到以下响应:
{
"statusCode": 401,
"error": "Unauthorized",
"message": "Missing authorization header"
}如果您发送经过身份验证的 GET 请求到 /private 路由,您将得到以下响应:
{
"secret": "This is a secret message",
"username": "alice"
}这证明了我们已经成功地为 Fastify 实现了访问控制和身份验证。
Source: FunTeaLearn,Please indicate the source for reprints https://funteas.com/post/67da2ce1a941bf71341ea207