对Windows 8 Metro JavaScript App使用jQuery导致安全错误
由于听起来像jQuery是Metro JavaScript应用程序的选项 ,我开始期待Windows 8开发。 我安装了Visual Studio 2012 Express RC并启动了一个新项目(空白和网格模板都有相同的问题)。
我做了一个jQuery 1.7.2的本地副本,并将其添加为脚本引用。
<!-- SomeTestApp references --> <link href="/css/default.css" rel="stylesheet" /> <script src="/js/jquery-1.7.2.js"></script> <script src="/js/default.js"></script>
不幸的是,一旦我运行了最终的应用程序,它抛出一个控制台错误:
HTML1701:无法添加dynamic内容'a'脚本尝试注入dynamic内容或先前被dynamic修改的元素,这可能是不安全的。 例如,使用innerHTML属性来添加脚本或格式错误的HTML会产生这个exception。 使用toStaticHTML方法过滤dynamic内容,或使用createElement等方法显式创build元素和属性。 有关更多信息,请参阅http://go.microsoft.com/fwlink/?LinkID=247104 。
我在jQuery的非缩小版本中打了一个断点,并find了违规的行 :
div.innerHTML = " <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
很明显,Metro应用程序的安全模型禁止以这种方式创build元素 。 这个错误不会给用户造成任何直接的问题,但是考虑到它的位置,我担心它会导致jQuery中的function发现testing失败。
我绝对想要jQuery $.Deferred
为了使一切更容易。 我宁愿能够使用select器引擎和事件处理系统,但是如果必须的话,我可以没有它们。
如何获得最新的jQuery与Metro开发很好的搭配?
您需要编辑jQuery源代码,以便将jQuery.support
函数传递给MSApp.execUnsafeLocalFunction
,从而禁用不安全的内容检查,如下所示:
jQuery.support = MSApp.execUnsafeLocalFunction(function() { var support, all, a, select, opt, input, fragment, tds, events, eventName, i, isSupported, div = document.createElement( "div" ), documentElement = document.documentElement; // lots of statements removed for brevity return support; });
您需要记住删除最后一对圆括号 – 您不需要自执行函数,因为execUnsafeLocalFunction
自动执行它传递的函数。
我build议更好的方法是使用WinJSfunction – 这包括WinJS.Promise
对象作为延迟操作(本身是Promise模式的实现)的替代方法。 你可以使用WinJS.Utilities
命名空间来做一些基本的DOM操作。
你应该考虑使用jQuery进行延期操作。 WinJS.Promise
对象在整个Metro API中用来表示asynchronous活动,并且最终将使用两种类似但不同的方法。
对于它的价值,我已经移植了大部分的jQuery核心来包装原生的WinJS库。 这是轻量级的,并提供了几乎所有的jQuery与增加一些徽章,通知等插件。
这是一项正在进行的工作,但我正在试图让一些人join进来。
https://github.com/rmcvey/winjq
快速写作(正在添加文档): http : //practicaljs.com/jquery-in-windows-8-apps/
在最近的// Build / 2012会议之后, 这个演讲谈到了在Windows 8商店应用中使用jQuery。 具体来说,他们会谈到innerHTML中脚本注入的确切例外,并且讨论在这里完成的更新。
在那次谈话中, AppendTo公司也正式推出了针对Windows 8的jQuery 。 它看起来整洁的说明中给出的演示链接。
他们还说,从本地上下文的Windows 8应用程序的CDN获取jQuery不是一个好主意!
GitHub上的JavaScript Dynamic Content shim由Microsoft Open Technologies创build并发布,以解决这个错误。 它尚未经过jQuerytesting,但很可能会解决您的问题。 在运行任何其他脚本之前,请参阅应用程序开始处的winstore-jscompat.js文件,而不应再看到此错误。
我做了更多的调查,并想澄清一些事情。
你看到的错误是在JavaScript控制台,而不是一个实际的例外。 jQuery代码继续运行得很好 。 它实际上是底层系统正在logging的东西,而不是错误或exception。
没有理由补丁jQuery或做任何事情 – 这是一个嘈杂的系统组件,而不是一个实际的错误。
我写了一个非常详细的解释如何使jQuery与Windows 8在这里工作http://davidvoyles.wordpress.com/2013/09/23/hacking-jquery-to-work-in-windows-8/
如果你仍然需要它,我正在写一个在jQuery中发现的Deferred对象的重新实现。
一旦完成,它应该与jQuery的Deferred对象100%兼容。 现在它是相当完整的,但需要一些testing。
看到这个
希望这会有所帮助!
这就是说,我认为在Windows 8应用程序上工作时学习如何使用微软的Promise而不是jQuery的应用程序是个好主意。
我相信这与内容安全策略(CSP)强加的是相同的限制。 jQuery 1.8.0解决了这个具体的案例。 问题是否仍然存在?
https://github.com/jquery/jquery/commit/dc83072878ed9636c8158a014bd9fa4acc1ccce3
jQuery本身并没有在最新版本中抛出这样的例外,只要我replace了所有的表单代码,例如:
$('<input type="button" value="Press Me" />')
同
$(toStaticHTML('<input type="button" value="Press Me" />'))
请注意,并非所有的HTMLstring都被认为是不安全的,例如:
$('<span></span>')
不抛出任何例外。 不过jQuery仍然会抛出exception,如果你做这样的事情:
var div = '<div class="' + classesToApply + '"'; div += attrToAdd; div += '</div>'; $(div).appendTo(container);
以上不是使用jQuery的良好实践的例子,仍然有人这样做,所以你可能会遇到错误。 注意上面的代码不会像第一个代码片段那样生成相同的错误,而是会在jQuery.append中引发错误。 这个错误仍然通过执行$(toStaticHTML(div)).appendTo(container);
我能够通过在jQuery中find所有设置innerHTML并用toStaticHTML()
设置的值来消除问题。
所以,例如:
div.innerHTML = " <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
成为:
div.innerHTML = toStaticHTML(" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>");
为了安全起见,我还在jQuery定义之前定义了这个,以防文件在普通浏览器中使用:
window.toStaticHTML = window.toStaticHTML || function (s) { return s; };
对我来说,这似乎是最安全的变化,虽然它需要修补jQuery的十几个地方。 (不要在toStaticHTML之前使用var语句)