【问题标题】:Using jQuery with Windows 8 Metro JavaScript App causes security error将 jQuery 与 Windows 8 Metro JavaScript App 一起使用会导致安全错误
【发布时间】:2012-06-07 05:46:15
【问题描述】:

因为它听起来像jQuery was an option for Metro JavaScript apps,我开始期待 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:无法添加动态内容“a”脚本试图注入动态内容,或者 以前动态修改的元素,这可能是不安全的。为了 例如,使用 innerHTML 属性添加脚本或格式错误的 HTML 会产生这个异常。使用 toStaticHTML 方法进行过滤 动态内容,或显式创建元素和属性 方法,例如 createElement。有关详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkID=247104.

我在非缩小版的 jQuery 中打了一个断点,发现 the offending line:

div.innerHTML = "   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";

显然,Metro 应用程序的安全模型forbids creating elements this way。这个错误不会给用户带来任何直接的问题,但考虑到它的位置,我担心它会导致 jQuery 中的功能发现测试失败,这是不应该的。

我绝对想要 jQuery $.Deferred 让一切变得更容易。我希望能够使用选择器引擎和事件处理系统,但如果必须的话,我宁愿不用它们。

如何让最新的 jQuery 与 Metro 开发完美配合?

【问题讨论】:

  • 你是通过cdn加载jquery吗?
  • 没有。这是本地 jQuery 代码执行中触发的错误。
  • 顺便说一句,看起来我可以学习 new promise system 而不是 jQuery 的 $.Deferred
  • jQuery 1.8 需要另外两项修改才能完美地与 Windows 8 一起工作。我写了一个Blogpost,其中涵盖了必要的更改,提供了一些背景信息并提供了 jQuery 1.8 的“修补”版本。
  • 这是在 Windows 8 上使用 jQuery 的好资源:incloud.de/2012/08/windows-8-using-jquery-for-app-development

标签: jquery microsoft-metro winjs visual-studio-2012


【解决方案1】:

您需要编辑 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 会自动执行它传递的函数。

我建议更好的方法是使用 WinJS 功能 - 这包括 WinJS.Promise 对象作为延迟操作的替代方案(它们本身是 Promise 模式的实现)。并且您可以使用 WinJS.Utilities 命名空间进行一些基本的 DOM 操作。

您应该三思而后行使用 jQuery 进行延迟操作。 WinJS.Promise 对象在整个 Metro API 中用于表示异步活动,您最终将使用两种相似但不同的方法。

【讨论】:

  • 太棒了,这也困扰着我,修复工作完美。如果有人不介意这样做或不想弄乱 jQuery 源代码,这是我刚刚为自己创建的缩小版本:pastebin.com/0NC6XBFp.
  • 作为一个数据点,jQuery 1.7.1 不会导致这个错误,它是新的,在 1.7.2 中发生了一些变化。
  • 这无疑解释了所有关于在 Metro 中使用 jQuery 的博客文章,没有人遇到任何问题。它们大多是在 VS12 处于开发预览阶段(2011 年 9 月 16 日发布)时编写的,在 jQuery 1.7.2(2012 年 3 月 21 日发布)之前。
  • 奇怪 - 我刚刚尝试了 Win8 和 jQuery 1.7.2 的新发布预览版,一切正常,没有安全错误。这里发生了一些奇怪的事情......
  • Adam,您遇到的是第一次机会异常还是未处理的异常?如果您在调试器的对话框中点击“继续”,应用程序会死掉还是继续运行?如果它继续运行,它实际上不是问题,它只是一个已处理的异常。如果应用程序死了,那么就会发生其他事情。
【解决方案2】:

这是你的答案

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

适用于 windows 8 的官方 jquery 库

【讨论】:

  • 该项目已“终止”,因为它的作者说问题已由 jQuery 2.0 修复;但是 jQuery 2.1.0 和 VisualStudio 2013 仍然会出现问题...
  • 事实上 jQuery 2.0.2 不会出现问题,所以 2.0.2 和 2.1.0 之间似乎存在回归
  • 这个问题在 jQuery 2.2.4 和 3.1.0 中仍然存在,在 WP8 应用程序上不能进行 append() 操作。
【解决方案3】:

不管怎样,我已经移植了大部分 jQuery 核心来包装原生 WinJS 库。它是轻量级的,几乎提供了 jQuery 所做的一切,并添加了一些用于徽章、通知等的插件。

这是一项正在进行的工作,但我正在努力让一些人加入其中。

https://github.com/rmcvey/winjq

快速撰写(正在添加文档):http://practicaljs.com/jquery-in-windows-8-apps/

【讨论】:

  • 很棒的图书馆,希望你继续努力:)
  • 是的,我将它用于 Answers.com Windows 8 应用程序;您对图书馆有什么具体问题吗?
【解决方案4】:

在最近的 //Build/ 2012 会议之后,this talk 谈到了在 Windows 8 应用商店应用程序中使用 jQuery。具体来说,他们在 innerHTML 中讨论了 脚本注入 的确切例外,并讨论了其中所做的更新。

公司 AppendTo 在那次谈话中也正式公布了jQuery for Windows 8。从链接中的演讲中给出的演示来看,它看起来很整洁。

他们还说,在本地上下文中从 CDN 为 Windows 8 应用程序获取 jQuery 不是一个好主意!

【讨论】:

  • 完全正确——来自 CDN 的 jQuery 将不起作用,因为它会引发错误。您需要下载最新版本并将其存储在本地以供您的项目使用。
【解决方案5】:

GitHub 上的 JavaScript Dynamic Content shim 由 Microsoft Open Technologies 创建并发布,以解决此错误。它尚未使用 jQuery 进行测试,但很可能会解决您的问题。在运行任何其他脚本之前,请在应用程序的开头引用 winstore-jscompat.js 文件,您应该不会再看到此错误。

【讨论】:

  • 谢谢。这适用于 AngularJS,所以我认为它也适用于 jQuery。
  • 谢谢!!如果可以的话,我会给你的答案投票 10 次,这确实是 Windows 问题的最终解决方案。现在我可以正常使用jQuery 2.x了。我浪费了几个小时四处寻找解决方案,谢谢。我现在就给你投票。
【解决方案6】:

我做了更多调查,想澄清一些事情。

您看到的错误是在 JavaScript 控制台中,而不是实际的异常。 jQuery 代码继续运行很好。这实际上是底层系统正在记录的内容,而不是错误或异常。

没有理由修补 jQuery 或做任何其他事情 - 这是一个嘈杂的系统组件,而不是实际错误。

【讨论】:

  • 我的应用强制在尝试忽略此错误消息时关闭。
  • 你在哪里看到这个 - 你是在第一次加载 jquery .js 文件时得到它,还是因为你正在做的事情?
  • 我的应用在“噪音”下运行良好,但我想知道这是否会让代码审查者从 Windows 8 应用商店拒绝你的应用。
【解决方案7】:

我在这里写了一个关于如何让 jQuery 与 Windows 8 一起工作的非常详细的解释 http://davidvoyles.wordpress.com/2013/09/23/hacking-jquery-to-work-in-windows-8/

【讨论】:

【解决方案8】:

如果您仍然需要它,我正在编写 jQuery 中的 Deferred 对象的重新实现。

一旦完成,它应该与 jQuery 的 Deferred 对象 100% 兼容。现在它已经很完整了,但需要一些测试。

this

希望这会有所帮助!

也就是说,我认为在处理 Windows 8 应用程序时,学习如何使用 Microsoft 的 Promise 实现而不是 jQuery 应该是一个好主意。

【讨论】:

    【解决方案9】:

    我相信这与内容安全策略 (CSP) 施加的限制相同。 jQuery 1.8.0 解决了该特定情况。问题是否仍然存在?

    https://github.com/jquery/jquery/commit/dc83072878ed9636c8158a014bd9fa4acc1ccce3

    【讨论】:

    • 是的,VisualStudio 13 和 jQuery 2.1.0 仍然存在问题
    • 你向bugs.jquery.com举报了吗?请务必对您所看到的问题进行清晰的解释,而不仅仅是指向此页面的指针,因为它是旧的并且指的是旧问题。
    【解决方案10】:

    jQuery 本身并没有在最新版本中为我抛出此类异常,只要我替换了表单的所有代码,例如:

    $('<input type="button" value="Press Me" />')
    

    $(toStaticHTML('<input type="button" value="Press Me" />'))
    

    请注意,并非所有 HTML 字符串都被认为是不安全的,例如:

    $('<span></span>')
    

    不抛出任何异常。但是,如果您执行此类操作,jQuery 仍然会在追加时引发异常:

    var div = '<div class="' + classesToApply + '"';
    div += attrToAdd;
    div += '</div>';
    
    $(div).appendTo(container);
    

    以上不是使用 jQuery 的良好实践示例,但仍有一些人这样做,因此您可能会遇到错误。请注意,上面的代码不会产生与第一个 sn-p 相同的错误,而是在 jQuery.append 中引发错误。通过执行$(toStaticHTML(div)).appendTo(container);仍然可以修复此错误

    【讨论】:

      【解决方案11】:

      我能够通过在 jQuery 中找到所有设置 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 语句)

      【讨论】:

      • 谨慎使用这种方法,因为toStaticHTML 可能会彻底改变您的字符串。例如,在第一个示例中,虽然您以&lt;link/&gt; 标记开始,但在通过toStaticHTML 之后,您将不再拥有该标记。其他被删除的内容包括 HTML5 数据属性。
      • 同意。我们尝试了这种方法。但它从我们试图传递的标签中剥离了所有数据。没用。
      猜你喜欢
      • 1970-01-01
      • 2011-06-30
      • 2013-11-11
      • 2014-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-21
      • 1970-01-01
      相关资源
      最近更新 更多