ajax请求返回一个标有我用户输入的JSON数组。输入已经过清理,使用eval()函数,我可以轻松创建我的javascript对象并更新我的页面......
所以这就是问题所在。无论我如何努力消毒输入,我宁愿不使用eval()函数。我已经检查了谷歌使用“没有评估的AJAX中的JSON”的方法,并且运行了很多不同的方法......
我应该使用哪一个?是否有一种标准的,经过验证的安全方法?
答案 0 :(得分:21)
json.org有一个很好的javascript library
简单用法:
JSON.parse('[{"some":"json"}]');
JSON.stringify([{some:'json'}]);
编辑:正如评论中所指出的,如果您查看其来源,它会使用eval(尽管它看起来首先要清理)
要完全避免,请查看json_parse或json-sans-eval
json2.js不安全,json_parse.js很慢,json-sans-eval.js无法验证
答案 1 :(得分:11)
是否有标准的,经过验证的安全方法?
在即将推出的ECMAScript 3.1版JavaScript中,有一种建议的标准方法:JSON.parse。
它将在IE8,Firefox 3.1 / 3.5以及未来很可能是其他流行的浏览器中得到支持。在此期间,您可以退回或专门使用eval()。邪恶可能会也可能不会;当然它会比JSON.parse慢。但这是今天解析JSON的常用方法。
如果攻击者能够将狡猾的JavaScript注入您通过JSON吐出的内容,那么您需要担心的问题比eval-is-evil更大。
答案 2 :(得分:9)
我想说,一旦输入被消毒,eval就是最好的方式。如果您的服务器遭到入侵,人们将无论如何都能够将他们想要的任何脚本发送给客户端。所以放一个评估并不是一个很大的安全风险。如果您担心人们在到达客户端之前操纵数据包,那么可以再次修改脚本本身。
不要担心eval。但请确保将其包装在try ... catch块中,这样如果您的JSON被破坏,您的用户就不会收到JS错误。
:)
答案 3 :(得分:2)
要将JSON安全地转换为JS对象,您应该使用JSON解析器,例如this library提供的JSON.parse()函数。
答案 4 :(得分:0)
与命令设计模式进行比较:http://en.wikipedia.org/wiki/Command_pattern。鉴于此,您可以精确定义客户端可以执行的操作,并且您的应用程序将与基础解释一样安全。
答案 5 :(得分:0)
取决于您在环境卫生方面要做的事情。 prototype框架支持JSON和安全评估,我取得了很大的成功。
答案 6 :(得分:0)
如果您确定没有注射风险,并且您在循环中不是eval()ing
,请使用eval()
。它将与其他选项相媲美,这些选项肯定会变慢,可能会中断,并且需要客户端下载其他代码。
答案 7 :(得分:0)
// Try to use the native JSON parser first
return window.JSON && window.JSON.parse ?
window.JSON.parse( data ) :
(new Function("return " + data))();
答案 8 :(得分:0)
<强>问题:强> eval带来的问题是它在全局范围内执行
eval.call(document, "console.log(this)")
eval.call(navigator, "console.log(this)")
eval.call(window, "console.log(this)")
(function(){eval.call(document, "console.log(this)")})()
>Window
<强>情境:强>
假设您在各种文档元素的标记代码中使用单个属性,例如属性 onvisible
<img src="" onvisible="src='http://www.example.com/myimg.png';">
您希望获取具有此属性的所有元素,将onvisible-content-string转换为闭包并将其放入EventHandler队列。这是JS函数构造函数发挥作用的地方。
Function === 0..constructor.constructor
>true
Function('return [this, arguments]').call(window, 1,2,3)
>Window, Arguments[3]]
Function('return [this, arguments]').call(document, 1,2,3)
>Document, Arguments[3]]
Function('return [this, arguments]').call(navigator, 1,2,3)
>Navigator, Arguments[3]]
全部放在一起:
var eventQueue = [];
var els = document.querySelectorAll('[onvisible]');
for (var el in els) {
var jscode = els[el].getAttribute('onvisible');
eventQueue.push( {el:els[el], cb:Function(jscode)} )
}
//eventQueue[0].cb.call(scope, args);