使用fastify-jwt生成含用户ID的Token时报“Expected "options" to be a plain object”错误的解决方法
解决Fastify JWT登录功能的500错误问题
嘿,我来帮你搞定这个登录功能的问题~
错误原因分析
你遇到的"Expected 'options' to be a plain object."错误,核心问题出在两个地方:
fastify-jwt的sign方法第二个参数需要是配置选项对象(比如设置过期时间、算法等),而不是直接传入字符串密钥。你已经在注册插件时全局配置了密钥,调用sign时完全不需要重复传入密钥。- 代码缺少边界处理:如果用户输入的邮箱/密码错误,
foundUser会是undefined,这时候直接解构{ id }会抛出新的异常,直接触发500错误。
修正后的完整代码
import Fastify from "fastify"; import fastifyJwt from "fastify-jwt"; import { users } from "../dummy-data/users.js"; const fastify = Fastify(); const SECRET_KEY = "secret"; // 全局注册JWT插件并配置密钥 fastify.register(fastifyJwt, { secret: SECRET_KEY }); // 注册登录路由,确保请求能映射到处理函数 fastify.post('/signin', signIn); const signIn = function (req, res) { const { email, password } = req.body; // 1. 先校验请求参数是否完整 if (!email || !password) { return res.status(400).send({ message: "邮箱和密码不能为空" }); } // 2. 查找匹配的用户 const foundUser = users.find( (user) => user.email === email && user.password === password ); // 3. 处理用户不存在/密码错误的情况 if (!foundUser) { return res.status(401).send({ message: "邮箱或密码错误" }); } // 4. 生成Token:只传入包含用户ID的payload即可 const accessToken = fastify.jwt.sign({ id: foundUser.id }); return res.status(200).send({ accessToken }); } // 启动Fastify服务 fastify.listen({ port: 3000 }, (err) => { if (err) { fastify.log.error(err); process.exit(1); } console.log('服务已启动在 http://localhost:3000'); });
关键修改点说明
- 修正JWT签名调用:去掉了
sign方法的第二个密钥参数,只传入用户ID的payload即可。因为插件已经全局配置了secret,会自动使用该密钥完成签名。如果需要临时使用不同密钥,才需要在第二个参数对象里指定secret,比如fastify.jwt.sign({ id }, { secret: "another-secret" })。 - 增加参数校验:提前检查请求体的邮箱和密码是否存在,返回400错误提示,避免无效查询。
- 增加错误边界处理:当未找到匹配用户时,返回401未授权错误,避免解构
foundUser.id时抛出异常。 - 补充路由注册:补上了你之前省略的路由注册代码,确保前端请求能正确触发
signIn处理函数。
内容的提问来源于stack exchange,提问作者Evan
相关产品推荐
相关产品推荐

