对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活动,并且最终将使用两种类似但不同的方法。

这是你的答案

https://github.com/appendto/jquery-win8

它的官方jquery库的Windows 8

对于它的价值,我已经移植了大部分的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语句)