我正在实现 Content Security Policy使用以下策略的 header
Content-Security-Policy: default-src 'self'
因此需要避免内联脚本,因为它不会执行。
但是,在 MVC 应用程序中,某些功能(例如编辑器模板)使用内联脚本。例如tinymce_jquery_full.cshtml
包含
$(function() {
$('#@ViewData.TemplateInfo.GetFullHtmlFieldName(string.Empty)').tinymce({
...
使用 CSP 时,在外部 .js
文件中包含动态值的好方法是什么?
我目前的想法是两种方式之一:
C# 生成的 JavaScript
类似于JSONP的方式有效,除了在 URL 中我没有指定回调 - 我只是传递动态值。在每个需要动态 JavaScript 的文件中,我都包含一个链接,例如
<script src="/script/Foo/bar"></script>
点击 ScriptController
的 Foo
操作返回类型为 text/javascript
的内容插入动态值 bar
。这让我觉得这是一种可靠的方法,如果有点笨拙并且它首先会破坏使用 CSP 的一些优势(几乎与没有 CSP 时一样容易意外插入未编码的文本并导致 XSS) .
隐藏表单域
动态值被插入到页面中:
<input type="hidden" id="url" name="url" value"http:://www.example.com/" />
并在外部 JavaScript 文件中查找这些值:
$('#url').val();
这会起作用,但如果页面上有多个动态控件或者如果有多个相同类型的控件,它可能会很尴尬。问题是如何有效地将每个 .js
脚本与其隐藏字段匹配。
是否有更好的解决方案或是否有任何现成的框架可供我使用?
最佳答案
$('#@ViewData.TemplateInfo.GetFullHtmlFieldName(string.Empty)')
是的,这通常不是一个好方法。 Razor 默认情况下会进行 HTML 转义,但这里的上下文不仅仅是 HTML,它是:
- 一个标识符,在里面
- 一个 CSS 选择器,在里面
- 内部的 JavaScript 字符串文字
- 一个 JavaScript 语句,在里面
- 一个 HTML CDATA 元素 (
<script>
)
所以只是 HTML 转义是错误的——任何在选择器或 JS 字符串文字上下文中特殊的字符(例如点、反斜杠、撇号、行分隔符......)都会破坏这个声明。
假设 GetFullHtmlFieldName
的结果,也许这对于这个特定示例来说并不是特别重要总是安全的,但对于一般情况来说这不是一个好的假设。
C# Generated JavaScript: a bit clunky and it kind of defeats some of the advantages of using a CSP
同意,避免这种情况。获得正确的缓存并将信息从生成页面内容的 ASP 传输到生成脚本的页面通常很痛苦。
另外生成 JavaScript 也不一定那么简单。 ASP 和 Razor 模板不会为您提供自动 JS 转义器。 JSON 编码几乎可以做到这一点,除了 JSON 和 JS 之间的细微差别(即 U+2028 和 U+2029)。
Hidden Form Fields
更一般地说,将信息放在 DOM 中。隐藏表单域是一种方法。 data-
属性是另一种常用的。无论哪种方式,我都非常喜欢 DOM 方法。
当使用隐藏的表单字段时,您应该删除 name
属性就好像它们在真实的 <form>
中一样您通常实际上并不想将传递给 JS 的数据提交。
这样您就可以使用正常的默认 HTML 转义将内容注入(inject)到模板中。如果您需要更多结构,您始终可以对要传递的数据进行 JSON 编码。 jQuery 的 data()
助手会自动 JSON.parse
在那种情况下,它们也适合你。
<body data-mcefields="@Json.Encode(GetListOfHtmlFields())">
...
var mce_array = $('body').data('mcefields');
$.each(mce_array, function() {
var element = document.getElementById(this);
$(element).tinymce({ ... });
});
(虽然...对于选择要应用 HTML 编辑器的元素的特定情况,也许更简单的方法只是使用 class="tinymce"
并应用 $('.tinymce').tinymce(...)
?)
关于c# - 在外部 JavaScript 文件中插入动态值的安全方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21428259/