在JavaScript中不使用eval()或new Function()处理字符串运算符
安全实现数据库存储的运算符运算逻辑
直接用白名单运算符映射的方案,完全规避eval或Function的安全与性能问题,核心思路是只允许预定义的合法运算符,通过函数映射执行运算:
1. 定义运算符映射表
把所有支持的运算符对应到具体的运算函数,只保留业务需要的运算符,拒绝任何未知操作:
// 白名单运算符映射,key是数据库存储的运算符,value是对应的运算函数 const operatorMap = { '===': (a, b) => a === b, '!==': (a, b) => a !== b, '>': (a, b) => Number(a) > Number(b), '<': (a, b) => Number(a) < Number(b), '>=': (a, b) => Number(a) >= Number(b), '<=': (a, b) => Number(a) <= Number(b), '+': (a, b) => Number(a) + Number(b), '-': (a, b) => Number(a) - Number(b), '*': (a, b) => Number(a) * Number(b), '/': (a, b) => Number(a) / Number(b), '%': (a, b) => Number(a) % Number(b) };
2. 实现安全执行函数
先校验合法性,再处理参数类型,最后执行运算:
function executeOperation(operator, param1, param2) { // 第一步:校验运算符是否在白名单内,非法直接抛出错误 if (!operatorMap.hasOwnProperty(operator)) { throw new Error(`不支持的运算符: ${operator}`); } // 第二步:根据运算符类型处理参数转换(数值运算转数字,全等/不等保留原类型) let processedParam1 = param1; let processedParam2 = param2; const numericOps = ['>', '<', '>=', '<=', '+', '-', '*', '/', '%']; if (numericOps.includes(operator)) { processedParam1 = Number(param1); processedParam2 = Number(param2); // 校验参数是否能转为有效数值 if (isNaN(processedParam1) || isNaN(processedParam2)) { throw new Error('参数不是有效的数值'); } } // 第三步:执行运算并返回结果 return operatorMap[operator](processedParam1, processedParam2); }
3. 示例用法
直接传入数据库获取的运算符和参数即可:
const operatorFromDB = '>'; const param1FromDB = '10'; const param2FromDB = '5'; try { const result = executeOperation(operatorFromDB, param1FromDB, param2FromDB); console.log(result); // 输出 true } catch (err) { console.error(err.message); // 处理非法运算符或无效参数的情况 }
安全与性能优势
- 完全规避注入风险:只允许白名单内的运算符,任何恶意构造的运算符(比如带代码片段的字符串)都会被直接拦截
- 性能更稳定:函数调用比
eval/Function的动态编译执行效率更高 - 类型可控:可以根据业务需求严格处理参数类型,避免隐式类型转换导致的意外结果
内容的提问来源于stack exchange,提问作者flow24
相关产品推荐
相关产品推荐

