我对 Fastify 相当陌生,我正在使用它来构建 API。我在路由中使用身份验证装饰器时遇到了一些麻烦,抛出以下错误:“code”:“FST_ERR_HOOK_INVALID_HANDLER”,“name”:“FastifyError”,“statusCode”:500},“msg”:“ preHandler hook 应该是一个函数,而不是得到 [object Undefined]”。
我已经在以下位置设置了一个装饰器文件 @/decorators/authentication.ts
import { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
import fjwt, { FastifyJWT } from "@fastify/jwt";
import fCookie from "@fastify/cookie";
import { env } from "@/config/constants"; // Ensure the correct path
export default async function authentication(app: FastifyInstance) {
// Register JWT plugin
app.register(fjwt, { secret: String(env.JWT_SECRET_KEY) });
// Register cookies plugin
app.register(fCookie, {
secret: env.JWT_SECRET_KEY,
hook: "preHandler",
});
// Decorate app with the authenticate function
app.decorate(
"authenticate",
async (req: FastifyRequest, reply: FastifyReply) => {
try {
const token = req.cookies.access_token;
if (!token) {
return reply.status(401).send({ message: "Authentication required" });
}
// Verify the token and set the user in the request object
const decoded = req.jwt.verify<FastifyJWT['user']>(token)
req.user = decoded;
} catch (err) {
return reply.status(401).send({ message: "Invalid or expired token" });
}
}
);
}
并使用它 @/modules/authentication/authentication.routes.ts
import { FastifyInstance } from "fastify";
import AuthenticationController from "./authentication.controller";
import UserService from "@/data-services/user-service";
import { $ref, userSchemas } from "./authentication.schema";
export default async function authRoutes(fastify: FastifyInstance) {
// Decorate fastify with the user service
fastify.decorate("userService", new UserService());
// Register schemas
userSchemas.forEach((schema) => fastify.addSchema(schema));
const authController = new AuthenticationController(fastify.userService);
// Login route
fastify.post(
"/login",
{
schema: {
body: $ref("loginSchema"),
response: {
201: $ref("loginResponseSchema"),
},
},
},
authController.login.bind(authController)
);
// Register route
fastify.post(
"/registro",
{
schema: {
body: $ref("registerUserSchema"),
response: {
201: $ref("registerUserResponseSchema"),
},
},
},
authController.register.bind(authController)
);
// Get current user route with preHandler for authentication
fastify.get(
"/me",
{
preHandler: [fastify.authenticate],
},
authController.getCurrentUser.bind(authController)
);
}
我将我的 server.ts 文件设置为这样
import Fastify from "fastify";
import { env } from "./config/constants";
import "./types";
import authentication from "@/decorators/authentication";
import routes from "./config/routes";
const app = Fastify({
logger: true,
});
const listeners = ["SIGINT", "SIGTERM"];
listeners.forEach((signal) => {
process.on(signal, async () => {
await app.close();
process.exit(0);
});
});
app.register(authentication);
app.register(routes);
app.listen(
{
port: env.PORT,
},
(err, address) => {
if (err) {
app.log.error(err);
process.exit(1);
}
app.log.info(`server listening on ${address}, PORT: ${env.PORT}`);
}
);
我正在 /me 路由上记录一个临时处理程序,但 fastify.authenticate 返回为未定义。谁能解释一下为什么会发生这种情况?
软件包版本
"@fastify/cookie": "^10.0.1",
"@fastify/jwt": "^9.0.1",
"fastify": "^5.0.0",
"fastify-zod": "^1.4.0",
也已经检查过这些解决方案 相关堆栈溢出主题 Github相关问题 但没有找到答案
我试图使用我之前创建的装饰器方法对用户进行身份验证,但似乎不起作用,因为我的路线抱怨身份验证未定义。我已经在路由之前注册了身份验证装饰器,并添加了日志以确认装饰器在路由之前已正确注册。
问题是
fastify.authenticate
返回 undefined
这是因为 export default async function authentication(app: FastifyInstance)
插件不使用 fastify-plugin
模块,因此当它注册时 app.register(authentication);
它会创建自己的上下文,不会影响 routes
模块。
要修复它,您需要包装该函数:
import fp from 'fastify-plugin'
export default fp(
async function authentication(app: FastifyInstance) { ... }
)
有用的读物: