我正在尝试制作一个Web应用程序,以使用AJAX刷新其内容,样式和脚本,因此该网站无需更新页面即可更新所有内容。
所以发生的事情是,我首先获取页面,并且在加载页面时,我使用ajax向服务器发出请求并获取html内容,然后再次请求获取样式,最后再次请求获取脚本并将其放在脚本标签中
<script> //The script goes here </script>
然后,我将script标签放在html内容的末尾,并用内容完全更新正文
<body>
The HTML content goes here
<script> //and here is the script </script>
</body>
请求成功并且内容加载,因此样式以及使用浏览器检查器工具时,我可以看到脚本标签中加载了脚本,但脚本未执行。
这是问题的概述,您可以在此处查看代码 https://codepen.io/Yousef-Essam/project/editor/ZJGxea
app.js提供index.html文件,然后索引文件获取script.js文件,该文件使用ajax发送两个请求以获取content.html文件和content.js文件并设置链接标记的href属性到样式文件。然后将content.js文件放入带有新内容的脚本标签中。尽管content.html已加载,样式文件也已加载,脚本已加载到script标签中,但脚本未执行。
为什么会发生这种情况,我该如何解决?
-更新-
问题可能出在使用innerHTML上,但是为什么它实际上不起作用。
此外,我认为eval可能是一个解决方案,但由于不鼓励使用eval,我希望有一个更好的解决方案
答案 0 :(得分:2)
这太长了,无法发布为评论,因此我将其作为答案发布。
您正确地注意到:
我认为eval可能是一个解决方案,但由于不鼓励使用eval,我希望有一个更好的解决方案
实际上,eval在任何语言中都是有问题的,因为它实际上允许运行中的程序将字符串视为代码。这样做的最大问题是,这为代码注入打开了大门(用外行的术语:黑客攻击)。但是,此建议更多是理论建议,而不是有关使用什么功能的建议。
eval
的建议是什么意思? Eval是任何允许将字符串解释为代码的函数或机制。不同的语言具有允许eval
发生的不同功能。例如,某些语言允许递归字符串插值。某些语言具有称为interp()
的功能,该功能产生一个子解释器。某些语言从字面上讲有一个叫做eval()
的函数。
JavaScript具有四种评估机制:
使用eval()
函数。
eval()
的任何字符串都被视为代码。设置脚本标签的src
属性
src
属性的值是要下载的javascript文件脚本标记的正文
innerHTML
设置脚本主体(自Netscape 4 –第一个使用javascript的浏览器以来) javascript:
URI协议
:
之后的所有内容都视为代码因此,您要尝试执行的是执行eval
。无论您是否使用eval
函数都无关紧要,您仍在尝试使用eval
进行innerHTML
(尽管不起作用)
eval
,有没有一种在页面上运行javascript的安全方法?有-至少对于现代浏览器而言。
现代浏览器实现了称为 subresource integrity 的功能。不幸的是,在编写此答案时,Edge不支持它。基本上,您可以计算js文件的哈希值(例如sha1),并在script标签中对其进行声明,以便浏览器可以确认js文件未被篡改。以下是一个示例:
<script src="https://cdn.example.com/script.js"
integrity="sha384-+/M6kredJcxdsqkczBUjMLvqyHb1K/JThDXWsBVxMEeZHEaMKEOEct339VItX1zB"></script>
这取决于。 eval
问题对您可能真的很重要。如果是这样,从设置了子资源完整性的外部源加载javascript是执行javascript的唯一安全方法。
但不是每个人都如此偏执。到目前为止,我们通常在没有此功能的情况下做得很好。以下是一些经验法则,无论您使用script标记还是调用eval()
,它们都可以缓解代码泄漏:
始终确保您仅执行静态javascript代码。不要尝试从字符串构造代码。
如果必须从字符串构造代码(例如,使用诸如Handlebars之类的模板语言或使用诸如Webpack或Browserify之类的捆绑器),则切勿在代码中包含任何用户生成的内容。您仍然可以通过发出Ajax请求而不是将其包含在代码中来加载内容。
如果您必须在代码中包含用户生成的内容,而不要确保对内容进行清理。有几种普遍接受的策略,例如禁止使用特殊字符(例如<
和>
和"
或转义特殊字符)。甚至还有库将为您做到这一点。
基本上我们要避免的情况是用户输入John"; console.log("gotcha");"
作为他们的名字,并且能够执行代码。
答案 1 :(得分:1)
HTML规范不允许解析使用innerHTML
(按照生活标准中的note under the text property description)在页面加载后动态添加为HTML标签的SCRIPT元素。
在不使用eval
来解析脚本的情况下,类似问题的答案在一次简单的搜索中并不明显-尽管它们可能存在,但我只看到了场外展示的替代技术。
这是一个不使用eval
的动态加载器。由于脚本的加载是异步的,因此它使用(err, data
类型的回调函数来指示何时可以调用脚本。
function loadScript( url, callback) {
var el = document.createElement("SCRIPT");
el.type = "text/javascript";
function finish( err) {
callback( err, err ? false : true);
}
el.onerror = finish;
if( el.readyState){ // <= IE 10
el.onreadystatechange = function(){
if( this.readyState == "complete"){
finish( null);
}
};
}
else {
el.onload = function() { finish(null) };
}
el.setAttribute("async", true);
el.src = url;
document.getElementsByTagName("HEAD")[0].appendChild( el);
}
// example call to load jQuery 3.2.1
loadScript( "https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js",
function (err, ok) {
if( err) {
console.log( "loading failed: " + err);
}
else {
console.log( "loading success");
}
}
);