如果将src
属性指定为元素的一部分,则元素标记本身script
内的任何代码script
都不会被执行。但是,您可以使用以下代码添加此功能。我从 Crockford(我相信是他)那里得到了这项技术,他在关于渲染性能和为此将脚本异步加载到页面中的无关主题的演讲中使用了它。
JavaScript:
(function() {
// Using inner class example from bobince's answer
var _gat = (function() {
var data= null;
return {
init: function(d) {
console.info("Configuration data: ", d);
data = d;
}
}
})();
// Method 1: Extract configuration by ID (SEE FOOT NOTE)
var config = document.getElementById("my-counter-apps-unique-and-long-to-avoid-collision-id").innerHTML;
// Method 2: search all script tags for the script with the expected name
var scripts = document.getElementsByTagName("script");
for ( var i=0, l=scripts.length; i<l; ++i ) {
if ( scripts[i].src = "some-script.js" ) {
config = scripts[i].innerHTML;
break;
}
}
_gat.init( eval("(" +config+ ")") );
})();
HTML:
<script type="text/javascript" src="some-script.js" id="my-counter-apps-unique-and-long-to-avoid-collision-id">
{some: "foo", config: "bar", settings: 123}
</script>
这两种方法都有其缺点:
使用唯一且不冲突的 ID 将使确定正确的脚本元素更加精确和快速;但是,这不是有效的 HTML4/XHTML 标记。在 HTML5 中,你可以定义任意属性,所以当时不会有问题
此方法是有效的 HTML 标记;但是,如果您的网址可能发生变化(例如:http vs https),我展示的简单比较很容易被破坏,并且可能需要更强大的比较方法
关于eval
两种方法都使用eval
. 关于这个特性的典型口头禅是“eval is evil”。然而,这与说在eval
不知道危险的情况下eval
使用是邪恶的。
在这种情况下,AFAIK,script
标签中包含的数据不会受到注入攻击,因为在将 HTML 解析为 DOM 时,一旦到达该元素,就会执行评估脚本(显示的代码)。之前可能已定义的脚本无法访问计数器script
标签中包含的数据,因为在执行它们时该节点不存在于DOM
树中。
可能的情况是,setTimeout
从先前包含的脚本中执行的定时良好的脚本可能能够在 counter 的script
包含和 eval 之间的时间运行;但是,这可能是也可能不是,并且如果可能的话,可能不会如此一致,具体取决于 CPU 负载等。
故事的道德,如果你担心的话,包括一个非eval
'ing JSON解析器并使用它来代替。