FastifyJWT验证URL参数Token报错:request.jwtVerify不是函数
问题:Fastify中使用request.jwtVerify()报错TypeError: request.jwtVerify is not a function
场景背景
通过邮件发送带JWT Token的验证链接,用户点击链接后后端接收GET请求,从URL查询参数中提取Token并验证,完成邮箱确认。但验证时触发错误:TypeError: request.jwtVerify is not a function。
相关代码
1. 生成邮箱验证Token并发送邮件
const emailToken = await reply.jwtSign({}, { sub: email, expiresIn: '7d' }); const messageData = { from: 'test@mail.com', to: 'test@mail.com', subject: 'Verificação de E-mail', text: `Clique neste link para verificar seu e-mail: ${env.APP_URL}/users/verify/email?token=${emailToken}`, html: `<p>Clique neste <a href="${env.APP_URL}/users/verify/email?token=${emailToken}">link</a> para verificar seu e-mail.</p>` } // 发送验证邮件 const resMG = await mgClient.messages.create(env.MAILGUN_DOMAIN, messageData); console.log('Email enviado com sucesso: ', resMG)
2. 接收请求并验证Token的路由代码
import { makeVerifyUserEmailUseCase } from "@/application/factories/user/make-verify-user-email-use-case" import { FastifyReply, FastifyRequest } from "fastify" import { z } from "zod" export default async function verifyUserEmail(request: FastifyRequest, reply: FastifyReply) { const verifyUserEmailQuerySchema = z.object({ token: z.string(), }) const { token } = verifyUserEmailQuerySchema.parse(request.query) console.log('TOKEN after parse: ', token) try { const decodedToken = request.jwtVerify({ token } as any, (error, decodedToken) => { if (error) { console.log('ERROR!') console.error(error) return reply.status(401).send('Erro na verificação do token') } return decodedToken }) console.log('DECODED TOKEN: ', decodedToken) const emailToken = (decodedToken as any).sub.email console.log(emailToken) if ((decodedToken as any) && (decodedToken as any).sub?.email) { const verifyUserEmailUseCase = makeVerifyUserEmailUseCase() await verifyUserEmailUseCase.execute(emailToken) return reply.status(200).send({ message: 'E-mail verificado com sucesso!' }) } } catch (error) { console.error(error) } }
3. FastifyJWT插件配置
import fastifyJwt from '@fastify/jwt' app.register(fastifyJwt, { secret: env.JWT_SECRET, cookie: { cookieName: 'refreshToken', signed: false, }, sign: { expiresIn: '10m', }, })
错误原因
- 方法用途误解:
request.jwtVerify()是FastifyJWT提供的路由前置验证钩子,用于自动从请求头(Authorization Bearer)或配置的Cookie中提取Token并验证,不支持手动传入Token的调用方式。 - 方法名称混淆:直接验证自定义Token的正确方法是
request.jwt.verify(),属于request.jwt对象下的方法,而非request.jwtVerify()。
解决方法
1. 使用正确的验证方法
替换request.jwtVerify()为request.jwt.verify(),该方法支持直接传入Token字符串进行验证,返回解码后的内容。
2. 调整为异步Promise写法
避免使用回调,改用async/await处理验证逻辑,更符合代码风格。
3. 修正Token字段获取逻辑
生成Token时sub直接赋值为email,解码后decodedToken.sub即为邮箱地址,无需额外.email取值。
修改后的完整路由代码
import { makeVerifyUserEmailUseCase } from "@/application/factories/user/make-verify-user-email-use-case" import { FastifyReply, FastifyRequest } from "fastify" import { z } from "zod" export default async function verifyUserEmail(request: FastifyRequest, reply: FastifyReply) { const verifyUserEmailQuerySchema = z.object({ token: z.string(), }) const { token } = verifyUserEmailQuerySchema.parse(request.query) try { // 使用request.jwt.verify()直接验证Token const decodedToken = await request.jwt.verify(token) // 直接从sub获取邮箱 const userEmail = decodedToken.sub as string if (!userEmail) { return reply.status(400).send('Token inválido: não contém e-mail') } const verifyUserEmailUseCase = makeVerifyUserEmailUseCase() await verifyUserEmailUseCase.execute(userEmail) return reply.status(200).send({ message: 'E-mail verificado com sucesso!' }) } catch (error) { console.error(error) return reply.status(401).send('Erro na verificação do token') } }
内容的提问来源于stack exchange,提问作者Thiago Kosudi
相关产品推荐
相关产品推荐

