在外部JavaScript文件中插入动态值的安全方法
我正在使用以下策略实现内容安全策略标头
Content-Security-Policy: default-src 'self'
所以需要避免内联脚本,因为它不会执行。
但是,在MVC应用程序中,某些function(如编辑器模板)使用内联脚本。 例如tinymce_jquery_full.cshtml
包含
$(function() { $('#@ViewData.TemplateInfo.GetFullHtmlFieldName(string.Empty)').tinymce({ ...
使用CSP时,在外部.js
文件中包含动态值的好方法是什么?
我目前的想法是两种方式之一:
C#生成的JavaScript
类似于JSONP的工作方式,除了在URL中我没有指定回调 – 我只是传递动态值。 在每个需要动态JavaScript的文件中,我都包含一个链接,例如
它命中ScriptController
的Foo
动作,它返回插入动态值bar
text/javascript
类型的内容。 这对我来说是一种可靠的方式,如果有点笨拙,它首先会破坏使用CSP的一些优点(几乎很容易意外地插入未编码的文本并导致XSS,因为它没有CSP)。
隐藏的表单字段
动态值将插入页面:
并在外部JavaScript文件中查找这些值:
$('#url').val();
这将有效,但如果页面上有多个动态控件或者有多个相同类型的控件,则可能会很麻烦。 问题是如何有效地将每个.js
脚本与其隐藏字段匹配。
有没有更好的解决方案,还是有任何我可以使用的现成框架?
$( ‘#@ ViewData.TemplateInfo.GetFullHtmlFieldName(的String.Empty)’)
是的,这不是一般的好方法。 Razor默认会HTML转义,但上下文不仅仅是HTML,它是:
- 里面有一个标识符
- 里面有一个CSS选择器
- 里面有一个JavaScript字符串文字
- 里面有一个JavaScript语句
- HTML CDATA元素(
)
所以只是HTML转义是错误的 - 在选择器或JS字符串文字(如点,反斜杠,撇号,行分隔符......)的上下文中特殊的任何字符都会破坏这个语句。
也许这对于这个特定的例子来说并不是非常重要,假设GetFullHtmlFieldName
的结果总是安全的,但对于一般情况来说这不是一个好的假设。
C#生成的JavaScript:有点笨拙,它有点挫败了使用CSP的一些优点
同意,避免这种情况。 获得正确的缓存并将生成页面内容的ASP中的信息传输到生成脚本的页面通常很痛苦。
生成JavaScript也不一定非常简单。 ASP和Razor模板不会为您提供自动JS转发器。 除了JSON和JS之间的琐碎差异(即U + 2028和U + 2029)之外,JSON编码几乎可以实现。
隐藏的表单字段
更一般地说,将信息放在DOM中。 隐藏的表单字段是一种方法; data-
属性是另一种常用的属性。 无论哪种方式,我都非常喜欢DOM方法。
使用隐藏表单字段时,您应该删除name
属性,就好像它们位于真正的
您通常不想提交传递给JS的数据。
这样,您可以使用常规默认的HTML转义将内容注入模板。 如果您需要更多结构,您始终可以对要传递的数据进行JSON编码。 在这种情况下,jQuery的data()
帮助器也将自动为您提供JSON.parse
。
... var mce_array = $('body').data('mcefields'); $.each(mce_array, function() { var element = document.getElementById(this); $(element).tinymce({ ... }); });
(虽然......对于选择要应用HTML编辑器的元素的特定情况,也许更简单的方法就是使用class="tinymce"
并应用$('.tinymce').tinymce(...)
?)