eval()
以得出结果。然而,如果可以避免使用
eval()
,我总是回避它,因为它是有害的(而且,正确或错误地说,我一直认为在JavaScript中它甚至更加有害,因为要评估的代码可能会被用户更改)。那么,在什么情况下可以使用它呢?
eval()
以得出结果。eval()
,我总是回避它,因为它是有害的(而且,正确或错误地说,我一直认为在JavaScript中它甚至更加有害,因为要评估的代码可能会被用户更改)。eval
很少是正确的选择。虽然有很多情况下您可以通过将脚本连接在一起并即时运行来完成所需的工作,但通常您拥有更强大和可维护的技术:关联数组表示法(obj["prop"]
相当于 obj.prop
),闭包,面向对象技术,函数式技术 - 使用它们而不是 eval
。
{
"568ff113-abcd-f123-84c5-871fe2007cf0": {
"msg_enum": "quest/registration",
"timely": "all_times",
"scope": [
"quest/daily-active"
],
"query": "`SELECT COUNT(point) AS valid from \"${userId}/dump/quest/daily-active\" LIMIT 1`",
"validator": "valid > 0",
"reward_external": "ewallet",
"reward_external_payload": "`{\"token\": \"${token}\", \"userId\": \"${userId}\", \"amountIn\": 1, \"conversionType\": \"quest/registration:silver\", \"exchangeProvider\":\"provider/achievement\",\"exchangeType\":\"payment/quest/registration\"}`"
},
"efdfb506-1234-abcd-9d4a-7d624c564332": {
"msg_enum": "quest/daily-active",
"timely": "daily",
"scope": [
"quest/daily-active"
],
"query": "`SELECT COUNT(point) AS valid from \"${userId}/dump/quest/daily-active\" WHERE time >= '${today}' ${ENV.DAILY_OFFSET} LIMIT 1`",
"validator": "valid > 0",
"reward_external": "ewallet",
"reward_external_payload": "`{\"token\": \"${token}\", \"userId\": \"${userId}\", \"amountIn\": 1, \"conversionType\": \"quest/daily-active:silver\", \"exchangeProvider\":\"provider/achievement\",\"exchangeType\":\"payment/quest/daily-active\"}`"
}
}
直接通过json中的文字字符串注入对象/值,对于模板化文本非常有用
可用作比较器,例如我们可以制定规则来验证CMS中的任务或事件
如果未经充分测试,代码可能会出现错误并破坏服务。
如果黑客能够在您的系统上编写脚本,那么您就完蛋了。
验证脚本的一种方法是在某个安全的地方保留脚本的哈希值,以便在运行之前进行检查。
javascript:alert("hello");
<html>
<body>
<textarea id="output"></textarea><br/>
<input type="text" id="input" />
<button id="button" onclick="execute()">eval</button>
<script type="text/javascript">
var execute = function(){
var inputEl = document.getElementById('input');
var toEval = inputEl.value;
var outputEl = document.getElementById('output');
var output = "";
try {
output = eval(toEval);
}
catch(err){
for(var key in err){
output += key + ": " + err[key] + "\r\n";
}
}
outputEl.value = output;
}
</script>
<body>
</html>
<head></head>
不是也是必需的吗? - Peter MortensenEval并不是邪恶的,只是被误用了。
如果你创建的代码自己可信或者可以信任它,那么就没问题了。人们一直在谈论eval与用户输入无关,但有点类似~
如果有用户输入进入服务器,然后回到客户端,并且该代码在未经过消毒处理的情况下被用于eval中。恭喜你,你已经为用户数据发送给任何人打开了潘多拉魔盒。
根据eval所处的位置,许多网站使用SPAs,而eval可以使用户更容易地访问应用程序内部,否则将很难实现。现在他们可以制作虚假的浏览器扩展程序,可以录制该评估并再次窃取数据。
只需要弄清楚您使用eval的目的即可。当您可以简单地编写方法、使用对象或类似方法时,生成代码并不是理想的选择。
现在是使用eval的好例子。您的服务器正在读取您创建的swagger文件。许多URL参数的格式都是{myParam}
。因此,您希望读取URL,然后将其转换为模板字符串,而无需进行复杂的替换,因为您有许多端点。因此,您可以执行类似以下内容的操作。请注意,这只是一个非常简单的例子。
const params = { id: 5 };
const route = '/api/user/{id}';
route.replace(/{/g, '${params.');
// use eval(route); to do something
eval
对于Webassembly-Javascript互操作非常有用。虽然理想情况下,您应该在页面中包含预先制作的脚本,以便您的WASM代码可以直接调用,但有时不可行,您需要从Webassembly语言(如C#)传递动态Javascript来真正完成您需要做的事情。
在这种情况下,它也是安全的,因为您完全控制传入的内容。嗯,我应该说,在这种情况下,它并不比使用C#组合SQL语句更不安全,也就是说,每当使用用户提供的数据生成脚本时,都需要小心处理(正确转义字符串等)。但是,在互操作情况下,它有明确的位置,远非“邪恶”。
代码生成。我最近编写了一个名为Hyperbars的库,它在virtual-dom和handlebars之间架起了一座桥梁。它通过解析handlebars模板并将其转换为hyperscript来实现这一点。首先将hyperscript生成为字符串,然后在返回之前使用eval()
将其转换为可执行代码。在这种特定情况下,我发现eval()
恰恰相反是有益的。
基本上从
<div>
{{#each names}}
<span>{{this}}</span>
{{/each}}
</div>
转换为:
(function (state) {
var Runtime = Hyperbars.Runtime;
var context = state;
return h('div', {}, [Runtime.each(context['names'], context, function (context, parent, options) {
return [h('span', {}, [options['@index'], context])]
})])
}.bind({}))
eval()
的性能在这种情况下也不是问题,因为您只需要解释生成的字符串一次,然后多次重复使用可执行输出。
如果您好奇代码生成是如何实现的,可以在这里查看。
eval
提示某些应该在编译时处理的责任已经转移到运行时。 - Ruud Helderman我认为eval是客户端Web应用程序中非常强大的函数,也是安全的...与JavaScript一样安全,而JavaScript并不总是安全的。 :-) 安全问题本质上是服务器端的问题,因为现在有像Firebug这样的工具,可以攻击任何JavaScript应用程序。
eval
需要防止 XSS 攻击,这并不总是容易做到的。 - Benjamin如果您对传递给eval
函数的代码具有完全控制权,则可以使用它。
eval
的内容有完全的控制权,那么重要的问题就是,在什么情况下将其作为字符串而不是真正的 JS 是有意义的? - cHao<script async="true" src="...">
。另请参阅:https://w3bits.com/async-javascript/ - Ruud Helderman只要您能确保代码的来源来自您或实际用户,就没有理由不使用eval()。即使他可以操纵发送到eval()函数中的内容,这也不是一个安全问题,因为他能够操纵网站的源代码,从而改变JavaScript代码本身。
那么...什么时候不使用eval()?当存在第三方可能更改它时,就不应该使用Eval()。例如拦截客户端和服务器之间的连接(但如果这是一个问题,请使用HTTPS)。您不应该使用eval()来解析由其他人编写的代码,例如在论坛中。
eval
来组成自一个用户内容的字符串可能会允许该用户在其他用户的浏览器中执行代码。 - Mike Samuel