如何在Fastify中为路由设置Scope授权并实现权限校验
实现带参数的Fastify authenticate钩子用于权限校验
1. 修改authenticate装饰器为高阶函数
将原有的authenticate直接处理函数改为高阶函数,使其能接收权限参数并返回符合Fastify钩子要求的请求处理函数,以此实现带参数的调用方式。
修改后的JWT注册代码:
import fjwt from "@fastify/jwt"; import buildGetJwks from "get-jwks"; export default function register(fastify) { const getJwks = buildGetJwks({ providerDiscovery: false, jwksPath: ".well-known/openid-configuration/jwks", }); fastify.register(fjwt, { decode: { complete: true }, secret: (request, token) => { const { header: { kid, alg }, payload: { iss }, } = token; return getJwks.getPublicKey({ kid, domain: iss, alg }); }, formatUser: function (user) { return { scope: user.scope, }; }, }); // 改为高阶函数:接收权限参数,返回钩子处理函数 fastify.decorate("authenticate", function (requiredScope) { return async function (request, reply) { try { // 先验证JWT有效性,验证通过后request.user会被填充 await request.jwtVerify(); // 校验权限(若传入了requiredScope) if (requiredScope) { const userScope = request.user.scope; // 兼容scope为字符串(如"read write")或数组的情况 const userScopes = typeof userScope === 'string' ? userScope.split(' ') : userScope; if (!userScopes.includes(requiredScope)) { reply.code(403).send({ error: 'Forbidden', message: 'Insufficient permissions' }); return; } } } catch (err) { reply.send(err); } }; }); }
2. 在路由中使用带参数的authenticate
现在可以直接在onRequest钩子中传入带权限参数的调用,生成对应权限校验的钩子函数:
fastify.post( "/", { onRequest: [fastify.authenticate('create:news')], // 传入需要的权限scope }, async (req, reply) => { sem.take(async () => { let _news = createNews(req.body); if (_news) await generate(_news); sem.leave(); }); return { status: 'accepted' }; } );
关键逻辑说明
- 高阶函数的作用:让
authenticate能够接收权限参数,并返回一个绑定了该参数的请求处理函数,完全符合Fastify对onRequest钩子的签名要求。 - 权限校验流程:先完成JWT身份验证,再从
request.user中获取用户权限列表,校验是否包含目标权限;权限不足时返回403 Forbidden错误,JWT验证失败则直接返回原错误。
内容的提问来源于stack exchange,提问作者mohazh
相关产品推荐
相关产品推荐

