Why is using the JavaScript eval function a bad idea?eval函数是动态生成代码的一种强大而简单的方法,那么需要注意的是什么? 不正确使用eval会打开注入攻击代码 调试可能更具挑战性(无行号等) eval'd代码执行速度较慢(没有机会编译/缓存eval'd代码) 编辑:正如@jeff walden在评论中指出的那样,3今天比2008年更不真实。但是,虽然可能会发生编译脚本的某些缓存,但这将仅限于eval不做任何修改而重复的脚本。更可能的情况是,您正在评估的脚本每次都进行了轻微的修改,因此无法缓存。让我们假设一些eval'd代码执行得更慢。 埃瓦尔并不总是邪恶的。有时它是完全合适的。 然而,目前和历史上,eval被不知道自己在做什么的人过度使用。不幸的是,这包括编写JavaScript教程的人员,在某些情况下,这确实会带来安全后果——或者更常见的是,简单的错误。因此,我们越能在eval上面加上问号,效果越好。任何时候你使用疏散车,你都需要保持清醒,检查你在做什么,因为很有可能你会用更好、更安全、更清洁的方式。 为了给出一个非常典型的例子,设置一个ID存储在变量"potato"中的元素的颜色:
如果上面这类代码的作者对javascript对象的工作原理有了一些线索,他们就会意识到可以使用方括号而不是文字点名,这样就不需要进行eval了:
号 …更容易阅读,也不太可能有问题。 (但是,如果有人/真的/知道他们在做什么,他会说:
这比直接从文档对象访问dom元素这一老掉牙的技巧更可靠。) 我相信这是因为它可以从字符串中执行任何javascript函数。使用它使人们更容易将恶意代码注入应用程序。 我想到两点: 安全性(但只要您自己生成要评估的字符串,这可能不是问题) 性能:在要执行的代码未知之前,无法对其进行优化。(关于javascript和性能,当然是Steve Yegge的演示) 将用户输入传递给eval()是一个安全风险,但每次调用eval()都会创建一个新的javascript解释器实例。这可能是一种资源占用。 一般来说,只有通过eval用户输入时才会出现问题。 主要是,维护和调试要困难得多。它就像一个 要记住的一点是,您可以经常使用eval()在其他受限的环境中执行代码-有时在eval块中分解特定的javascript函数会愚弄那些阻止特定javascript函数的社交网站。-
。 所以,如果你想运行一些原本不允许的javascript代码(myspace,我在看你…),那么eval()是一个很有用的技巧。 但是,由于上述所有原因,您不应该将其用于您自己的代码,因为您完全可以控制这些代码——这是不必要的,最好将其放在"棘手的javascript黑客"工具架上。 除非让eval()成为动态内容(通过cgi或input),否则它与页面中的所有其他javascript一样安全可靠。 除了其他答案,我不认为eval语句可以高级最小化。 这是一个可能的安全风险,它有不同的执行范围,而且效率非常低,因为它为代码的执行创建了一个全新的脚本环境。有关更多信息,请参阅此处:eval。 但是,它非常有用,并且与适度一起使用可以添加很多好的功能。 除非您100%确信正在评估的代码来自可信的源(通常是您自己的应用程序),否则这是一种将系统暴露于跨站点脚本攻击的可靠方法。 如果你知道在什么环境中使用它,就不一定那么糟糕。 如果您的应用程序正在使用 不受信任的客户端JavaScript代码无论如何也不能做到这一点。如果你正在执行的 我知道这个讨论已经过时了,但我真的很喜欢Google的这种方法,我想和其他人分享这种感觉;) 另一件事是,你越能理解,你就越能理解,最后你只是不相信某件事是好是坏,只是因为有人这么说:)这是一个非常鼓舞人心的视频,它帮助我自己思考更多:)好的实践是好的,但不要盲目地使用它们:) 如果您希望用户输入一些逻辑函数并对其进行评估,那么javascript eval函数是完美的。我可以接受两个字符串和 它大大降低了你对安全的信心。 如果在代码中发现eval()的用法,请记住"eval()是邪恶的"这句咒语。 这个函数接受任意字符串并将其作为JavaScript代码执行。当代码在问题是预先知道的(在运行时不确定),没有理由使用eval()。如果代码是在运行时动态生成的,通常有更好的方法在不使用eval()的情况下实现目标。例如,只需使用方括号符号访问动态属性更好、更简单:
使用 同样重要的是要记住,向 在幕后,javascript仍然需要评估和执行作为编程代码传递的字符串:
号 使用新的函数()构造函数与eval()类似,应该接近它小心点。它可能是一个强大的结构,但经常被误用。如果你必须的话使用 潜力很小好处是,在new函数()中计算的代码将在本地函数中运行作用域,因此在被评估的代码中用var定义的任何变量都不会变为全局自动。 另一种防止自动全局调用的方法是 这是一篇很好的文章,讲的是eval,以及它如何不是一种邪恶:http://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misshood/
号 eval()非常强大,可以用于执行JS语句或计算表达式。但问题不在于eval()的使用,而在于您使用eval()运行的字符串如何受到恶意方的影响。最后,您将运行恶意代码。有了权力,责任就大了。所以明智地使用它就是你在使用它。这与eval()函数没有太多关系,但本文提供了非常好的信息:http://blogs.popart.com/2009/07/javascript-injection-attacks/如果要查找eval()的基础知识,请查看以下内容:https://developer.mozilla.org/en-us/docs/web/javascript/reference/global_objects/eval 随着下一代浏览器推出某种风格的JavaScript编译器,这可能成为一个更大的问题。通过eval执行的代码在这些新浏览器上的性能可能不如其他的javascript。有人应该做一些分析。 除了在执行用户提交的代码时可能出现的安全问题之外,大多数情况下还有一种更好的方法,不需要每次执行代码时都重新解析代码。匿名函数或对象属性可以替代eval的大部分用途,并且更安全、更快。 我想说的是,如果您在浏览器中运行的javascript中使用 所有的现代浏览器都有一个开发人员控制台,您可以在那里执行任意的javascript,任何半智能的开发人员都可以查看您的JS源代码,并将他们需要的任何部分放入开发人员控制台中,以执行他们想要的操作。 *只要您的服务器端点对用户提供的值进行了正确的验证和消毒,那么在客户端JavaScript中解析和评估什么就不重要了。 但是,如果您要询问是否适合在PHP中使用 我不会试图反驳之前所说的任何事情,但我会提供eval()的这种用法(据我所知),这种用法不能以任何其他方式进行。可能还有其他的方法来编写代码,也可能有一些方法来优化它,但是为了清晰起见,这是一个很长的过程,而且没有任何提示和口哨,以说明eval的使用实际上没有任何其他的选择。即:动态(或更准确地说)编程创建的对象名(而不是值)。
编辑:顺便说一句,我不建议(出于之前指出的所有安全原因)将对象名建立在用户输入的基础上。不过,我想不出有什么好理由让你这么做。不过,我想我会指出这不是个好主意:) javascript引擎在编译阶段执行了许多性能优化。其中一些归根结底就是能够在代码执行时对其进行静态分析,并预先确定所有变量和函数声明的位置,这样在执行期间解析标识符的工作就更少了。 但是,如果引擎在代码中发现一个eval(..),那么它本质上必须假定它对标识符位置的所有感知都可能是无效的,因为它无法在词法转换时准确地知道可以传递给eval(..)以修改词法作用域的代码,或者传递给它的对象的内容,从而创建一个新的要查询的词法作用域。 换句话说,在悲观的意义上,如果存在eval(..)的话,它所做的大多数优化都是毫无意义的,因此它根本就不执行优化。 这就解释了一切。 参考文献: https://github.com/getify/you dont know js/blob/master/scope%20&;%20闭包/ch2.md eval https://github.com/getify/you dont know js/blob/master/scope%20&;%20闭包/ch2.md性能 这并不总是个坏主意。例如,代码生成。我最近写了一个名为超链接的库,它弥合了虚拟DOM和把手之间的鸿沟。它通过解析一个手柄模板并将其转换为随后由虚拟DOM使用的超脚本来实现这一点。超脚本首先作为字符串生成,在返回它之前, 基本上来自
号 为了这个
在这种情况下, 如果您好奇的话,可以看到代码生成是如何实现的。 |