提问人:garydavenport73 提问时间:7/1/2022 最后编辑:Peter Mortensengarydavenport73 更新时间:12/16/2022 访问量:726
将 eval 用于客户端 JavaScript 计算器是否安全?
Is it safe to use eval for a client-side JavaScript calculator?
问:
我正在制作一个计算器,它作为用户浏览器的静态 HTML 页面。该页面不用于将任何信息提交回服务器。除了这个计算器之外,网页上不会出现任何其他内容。
在这种情况下使用“eval”是否安全?或者换一种说法,在这种情况下使用 eval 会不会造成额外的安全风险?
在我看来,用户似乎不能通过简单地打开浏览器开发工具来对这个页面做任何他们无法做到的事情。我一直读到“从不”使用 eval,但在这种情况下,这似乎很有意义。
下面是一个示例计算器:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Calculator</title>
</head>
<body>
<input id="input" type="text">
<button onclick="{
let result= '';
try {
result = eval(document.getElementById('input').value);
} catch (error) {
result = error;
}
console.log(result);
document.getElementById('result').innerHTML=result;
}">calculate</button>
<div id="result">result here</div>
</body>
</html>
答:
它可能会打开页面以执行任意代码。考虑一下是否有人设法说服您的一个或几个用户:“尝试将其粘贴到输入字段中。你不会相信接下来会发生什么!如果您在客户端上保存任何与用户相关的数据,例如 cookie 中的登录凭据,或本地存储或 IndexedDB 中的数据等,这是一个很大的潜在问题。
即使您不存储任何此类数据,对输入值进行清理也可能是一个好主意,以便它只包含数学表达式,而不包含其他任何内容。例如,只允许你想要的数字和运算符是微不足道的,也许.这很容易做到,而且很安全,所以你应该这样做。+-*/
另外,不要将函数放入内联处理程序中(或根本不使用内联处理程序)——这是非常糟糕的做法。使用 正确附加事件侦听器。addEventListener
document.querySelector('button').addEventListener('click', () => {
const sanitizedValue = document.getElementById('input').value
.replace(/[^-+/*\d]/g, '');
try {
document.getElementById('result').textContent = eval(sanitizedValue);
} catch(e) {
document.getElementById('result').textContent = 'Syntax not correct';
}
});
<input id="input" type="text">
<button>calculate</button>
<div id="result">result here</div>
.replace(/[^-+/*\d]/g, '');
做:
- 匹配任何不符合以下条件的字符:
-
, , ,+
/
*
- 或(任何数字)
\d
- 将所有此类匹配的字符替换为空字符串
评论
eval
eval
eval
永远不要使用 eval()
!
它来自 MDN,它还说:
幸运的是,有一个非常好的替代方法:使用构造函数。
eval()
Function
所以,你可以这样替换:eval()
let result= '';
try {
result = Function(`"use strict";return (${document.getElementById('input').value})`)();
}
catch (error) {
result = error;
}
它与 几乎相同,只是:eval
在不带 的函数中,对象在全局作用域中被计算,因此它是安全的
eval()
评论
eval
eval
评论