如何确保Hapi.js中scope永不为undefined?含Joi应用咨询
确保Hapi.js中auth.scope永不为undefined的方案
问题根源
当错误使用const roles = require('../permissions');(未解构)时,roles.read会指向undefined,此时Hapi的auth.scope被设为undefined,Hapi会默认跳过权限校验,导致受限用户能访问路由。我们需要通过多重手段确保scope始终为数组类型(空数组或合法权限数组)。
1. 导入环节兜底,避免undefined
方案A:给权限模块导出加兜底
在../permissions.js中确保导出结构稳定,即使模块逻辑出错也能返回默认结构:
// permissions.js module.exports = { roles: { read: ['user', 'admin'], write: ['admin'] } || {} // 兜底空对象,防止导出异常 };
方案B:导入时解构并兜底
导入时直接给roles和roles.read设置默认值,避免后续调用出现undefined:
const { roles = {} } = require('../permissions'); const requiredScope = roles.read || []; // 确保最终是数组 // 路由配置中使用requiredScope module.exports = { // ...其他配置 options: { auth: { strategy: 'simple', scope: requiredScope, }, }, };
2. 用Joi验证路由配置(直接解决你的需求)
可以用Joi在服务器启动前校验所有路由配置,强制auth.scope为数组类型,甚至自动设置默认值:
步骤1:定义路由配置的Joi Schema
const Joi = require('joi'); // 定义单个路由的校验规则 const routeSchema = Joi.object({ method: Joi.string().required(), path: Joi.string().required(), handler: Joi.func().required(), options: Joi.object({ auth: Joi.object({ strategy: Joi.string().required(), // 强制scope为字符串数组,默认空数组 scope: Joi.array().items(Joi.string()).default([]) }).required(), tags: Joi.array().items(Joi.string()), validate: Joi.object() }).required() });
步骤2:加载路由时校验
在加载所有路由的环节,逐个校验配置,不合法则直接抛出错误阻止启动:
const allRoutes = [ require('./routes/profile'), // 其他路由... ]; allRoutes.forEach(route => { const { error } = routeSchema.validate(route); if (error) { throw new Error(`路由配置错误 ${route.path}: ${error.message}`); } }); // 之后再注册路由到Hapi服务器 await server.route(allRoutes);
这样如果roles.read是undefined,Joi会自动将scope设为空数组,或者直接在启动阶段报错,避免线上出现权限漏洞。
3. 封装工具函数统一处理权限配置
写一个工具函数来生成auth配置,确保scope始终是数组:
// utils/auth.js function buildAuth(strategy, scope) { return { strategy, // 非数组类型直接转为空数组 scope: Array.isArray(scope) ? scope : [] }; }
在路由中使用:
const { buildAuth } = require('../utils/auth'); const { roles = {} } = require('../permissions'); module.exports = { method: 'GET', path: '/profile', handler: Customer.profile, options: { tags: ['api'], validate: {}, auth: buildAuth('simple', roles.read), }, };
4. Hapi全局auth兜底(辅助方案)
在服务器全局auth配置中设置默认scope为空数组,这样如果路由未显式设置scope,会使用默认值:
const server = Hapi.server({ /* 服务器配置 */ }); // 设置全局默认auth规则 server.auth.default({ strategy: 'simple', scope: [] // 默认空数组,拒绝无匹配权限的用户 });
注意:该方案仅能覆盖未设置auth.scope的路由,如果路由显式设置了scope: undefined,仍需配合前面的方案处理。
内容的提问来源于stack exchange,提问作者SunAns
相关产品推荐
相关产品推荐

