当前位置:  开发笔记 > 编程语言 > 正文

为什么使用JavaScript eval函数是一个坏主意?

如何解决《为什么使用JavaScripteval函数是一个坏主意?》经验,为你挑选了14个好方法。

eval函数是一种动态生成代码的强大而简单的方法,那么有什么警告呢?



1> Prestaul..:

    eval的不正确使用会打开您的注入攻击代码

    调试可能更具挑战性(没有行号等)

    eval'd代码执行速度较慢(无法编译/缓存eval'd代码)

编辑:正如@Jeff Walden在评论中指出的那样,#3今天不像2008年那样真实.但是,虽然编译脚本的某些缓存可能会发生,但这仅限于重复进行重复而无需修改的脚本.更可能的情况是,您正在评估每次都经过轻微修改的脚本,因此无法缓存.我们只说一些eval'd代码执行得更慢.


@EduardoMolteni,我们不关心(实际上也无法阻止)用户在自己的浏览器中执行js.我们试图避免的攻击是用户提供的值被保存,然后放入javascript并进行评估.例如,我可能会将我的用户名设置为:`badHackerGuy'); doMaliciousThings();`如果你拿我的用户名,把它连接到一些脚本并在其他人的浏览器中评估它然后我可以在他们的机器上运行我想要的任何javascript(例如强迫他们为我的帖子+1,将他们的数据发布到我的服务器等)
@Prestaul:由于假设的攻击者可以使用任何开发人员工具来更改客户端中的JavaScript,为什么你说Eval()打开你的代码注入攻击?还没开?(我当然是在谈论客户端JavaScript)
@TamilVendhan当然可以放断点.您可以通过在源代码中添加`debugger;`语句来访问Chrome创建的虚拟文件.这将停止在该行上执行您的程序.然后,您可以添加调试断点,就像它只是另一个JS文件.
一般来说,如果不是大多数函数调用,#1都是如此.eval()不应该被经验丰富的程序员挑选出来,只是因为没有经验的程序员滥用它.但是,有经验的程序员通常在他们的代码中拥有更好的架构,并且由于这种更好的架构,很少需要甚至考虑eval().
@JeffWalden,好评.我已经更新了我的帖子,虽然我发现自你发布以来已经过了一年.Xnzo72,如果你有点评价你的评论(正如杰夫所做的那样)那么我可能会同意你的看法.杰夫指出了关键:"多次eval相同的字符串可以避免解析开销".事实上,你错了; #3适用于许多场景.
@frodeborli,我不同意你的开场白.`eval`与函数调用根本不同.请阅读我对EduardoMolteni(2人以上)的评论,以获得解释.注入攻击特别指的是接受用户输入并允许它在自己的浏览器之外的某个地方执行.(例如服务器或其他用户的浏览器)但是,我同意,如果你很好地构建应用程序,很少需要`eval`.应该避免这种情况,因为几乎总有一种更好,更安全的解决方案.

2> bobince..:

评估并不总是邪恶的.有时候它非常合适.

然而,eval目前和历史上大量过度使用,他们不知道自己在做什么.不幸的是,这包括编写JavaScript教程的人,在某些情况下,这确实会带来安全后果 - 或者更常见的是简单的错误.因此,我们越多可以在eval上抛出问号,就越好.每当你使用eval时,你需要理智地检查你正在做什么,因为你可能会做得更好,更安全,更清洁.

举一个非常典型的例子,设置一个id存储在变量'potato'中的元素的颜色:

eval('document.' + potato + '.style.color = "red"');

如果上面那种代码的作者对JavaScript对象的工作原理有了线索,他们就会意识到可以使用方括号而不是文字点名,从而避免了对eval的需求:

document[potato].style.color = 'red';

...这更容易阅读,也不那么潜在的错误.

(但那时,某人/他/他们真正知道他们在做什么会说:

document.getElementById(potato).style.color = 'red';

这比直接从文档对象访问DOM元素的狡猾的旧技巧更可靠.)


嗯,我第一次学习JavaScript时觉得自己很幸运.我总是使用"document.getElementById"来访问DOM; 具有讽刺意味的是,我当时只是这样做,因为我不知道JavaScript中的对象是如何工作的;-)
@schoetbi:你不应该为JSON使用`JSON.parse()`而不是`eval()`吗?
@bobince有一些叫做特征检测和polyfill的东西来处理丢失的JSON库和其他东西(请看http://modernizr.com/)
同意.有时eval是可以的,例如来自webservices的JSON响应
@bobince http://code.google.com/p/json-sans-eval/适用于所有浏览器,https://github.com/douglascrockford/JSON-js也适用.Doug Crockford的json2.js确实在内部使用eval,但是使用了支票.此外,它还向前兼容JSON的内置浏览器支持.
当然,如果你愿意,你可以使用库.但是所有浏览器都必须下载库代码,即使它们具有本机支持,因此永远不会使用它.对于我确定JSON是安全的,并且作为JS文字和JSON有效的情况,我宁愿为'eval`节省额外的体积和丰满.

3> kemiller2002..:

我相信这是因为它可以从字符串中执行任何JavaScript函数.使用它可以让人们更容易将恶意代码注入应用程序.


我不买这个论点,因为已经很容易将恶意代码注入Javascript应用程序.我们有浏览器控制台,脚本扩展等...发送到客户端的每一段代码都是可选的,客户端可以执行.
关键是我更容易将代码注入您的浏览器.假设您在查询字符串上使用eval.如果我欺骗您点击链接到该网站并附上我的查询字符串,我现在已经在您的计算机上使用浏览器的完全权限执行了我的代码.我想要记录您在该网站上输入的所有内容并将其发送给我?完成,没有办法阻止我,因为当eval执行时,浏览器赋予它最高权限.
那么替代方案是什么?
真正的替代方案就是编写不需要它的代码.Crockford对此有所了解,如果你需要使用它,他几乎说它的程序设计缺陷并需要重新设计.事实上,我也同意他的观点.JS的所有缺陷都非常灵活,并且有很大的空间使其变得灵活.
事实并非如此,大多数框架都有一个解析JSON的方法,如果你没有使用框架,你可以使用JSON.parse().大多数浏览器都支持它,如果你真的很紧张,你可以很容易地为JSON编写一个解析器.
为什么有人会评估一个查询字符串?如今,您甚至不需要发布POST,更不用说GET了,因为有websocket。而且,您始终可以将iframe沙箱化,或使用网络工作者,在这两者之间只有“消息”之间进行通信,而彼此之间的名称空间却毫无关系。

4> xtofl..:

我想到两点:

    安全性(但只要您自己生成要评估的字符串,这可能不是问题)

    性能:直到要执行的代码未知,它无法进行优化.(关于javascript和性能,肯定是Steve Yegge的演讲)


为什么安全性是一个问题,如果客户端无论如何都可以使用他们想要的任何代码?Greasemonkey?
@PaulBrewczynski,当用户A将他的部分代码保存为"eval"时,会出现安全问题,然后,该小部分代码在用户的B浏览器上运行

5> Andrew Hedge..:

将用户输入传递给eval()存在安全风险,但每次调用eval()都会创建JavaScript解释器的新实例.这可能是资源匮乏.


在我回答这个问题后的3年多时间里,我对所发生事情的理解已经深化了.实际发生的是创建一个新的执行上下文.见http://dmitrysoshnikov.com/ecmascript/chapter-1-execution-contexts/

6> Mark Biek..:

如果您传递eval用户输入,通常只会出现问题.



7> Brian..:

主要是,维护和调试要困难得多.就像一个goto.您可以使用它,但这会使发​​现问题变得更加困难,并且对于可能需要稍后进行更改的人员更加困难.



8> matt lohkamp..:

要记住的一件事是,您通常可以使用eval()在受限制的环境中执行代码 - 阻止特定JavaScript函数的社交网站有时会被错误地在eval块中分解 -

eval('al' + 'er' + 't(\'' + 'hi there!' + '\')');

因此,如果你想要运行一些JavaScript代码,否则可能不会允许它(Myspace,我在看你......)然后eval()可能是一个有用的技巧.

但是,由于上面提到的所有原因,你不应该将它用于你自己的代码,你可以完全控制它 - 它只是没有必要,而且更好地降级到'棘手的JavaScript黑客'架子.


window ["al"+"er"+"t"]("这也可以成为一招吗?")
是的,有社交网站限制alert()但允许eval()?!
`[] ["con"+"struc"+"tor"] ["con"+"struc"+"tor"]('al'+'er'+'t(\''+'hi there!' +'\')')()`

9> Thevs..:

除非您让eval()成为动态内容(通过cgi或输入),否则它与您页面中的所有其他JavaScript一样安全可靠.


原来如此.我会称这些是动态的,因为客户不提前知道它们是什么,但我明白你的意思.

10> Paul Mendoza..:

除了其他答案之外,我认为eval语句不能具有高级最小化.



11> 小智..:

这是一种可能的安全风险,它具有不同的执行范围,并且效率非常低,因为它为代码的执行创建了一个全新的脚本环境.有关更多信息,请参阅此处:eval.

但它非常有用,并且适度使用可以添加许多好的功能.



12> John Topley..:

除非您100%确定所评估的代码来自可信来源(通常是您自己的应用程序),否则这是将您的系统暴露给跨站点脚本攻击的可靠方法.



13> MarkR..:

如果你知道你正在使用它的上下文,它不一定是那么糟糕.

如果您的应用程序eval()用于从某个JSON创建一个对象,该对象已从XMLHttpRequest返回到您自己的站点,由您的可信服务器端代码创建,则可能不是问题.

不受信任的客户端JavaScript代码无论如何都无法做到这一点.如果您正在执行的事情eval()来自合理的来源,那么你很好.


是不是只使用eval比解析JSON慢?

14> op1ekun..:

我知道这个讨论已经过时了,但我真的很喜欢Google的这种做法,并希望与他人分享这种感觉;)

另一件事就是越多越好你得到越多你试图理解,最后你只是因为有人这么说而不相信某事好或坏:)这是一个非常鼓舞人心的视频,帮助我自己多思考:)好的做法很好,但不要盲目使用它们:)

推荐阅读
路人甲
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有