如何使HTML /脚本注入的实时HTML预览textarea安全

时间:2017-03-31 19:50:24

标签: javascript jquery html spring-mvc velocity

我作为最后的手段转向这里。我已经搜索谷歌,我遇到麻烦来找到解决方案。我有一个带有textarea元素的表单,允许您在该区域中键入html,如果您预览模式处于活动状态,它将在您键入时实时显示HTML标记。与StackOverflow在新帖子下方显示预览的方式没有太大区别。

但是,我最近发现我的功能存在漏洞。我所要做的就是输入类似的东西:

</textarea>
     <script>alert("Hello World!");</script>
<textarea style="display: none;"> 

这不仅仅是在textarea实时内部运行,如果您保存表单并在不同页面上重新加载所述数据,此代码仍然在所述不同页面上的textarea内执行,但用户并不知情;对他们来说,所有的看法都是一个文本区(如果没有明显的警报)。

我找到了这个帖子; Live preview of textarea input with javascript html,并试图将我的JS重构为那里接受的答案,因为我注意到我无法在JSFiddle示例中编写脚本标记,尽管可能是某些JSFiddle阻止了这种行为,但我无法得到它在我的JS文件中工作。

这几行是我用来渲染HTML标记的内容:

$(".main").on("keyup", "#actualTextArea", function () {
    $('#previewTextArea').html($('#actualTextArea').val());
});

$(".main").on("keydown", "#actualTextArea", function () {
    $('#previewTextArea').html($('#actualTextArea').val());
});

有没有办法可以重构这样安全?我目前唯一的想法是擦除实时预览并使用切换开/关并对其进行编码,但我真的认为这是一个很酷的功能,并希望保持现场而不是切换。有没有办法“实时编码”它或逃避某些标签或什么?

2 个答案:

答案 0 :(得分:0)

为了清理文本区域预览,只需将所有<>替换为其等效的html字符代码:

&#13;
&#13;
function showPreview()
{
  var value = $('#writer').val().trim();
  value = value.replace("<", "&lt;");
  value = value.replace(">", "&gt;");
  $('#preview').html(value);
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="writer" onInput="showPreview();">
</textarea>
<br/>
<hr/>
<div id="preview">
</div>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

编辑:实际上,我认为这个解决方案有点清洁,并且不需要下面的代码。在velocity页面中,所需要的只是利用Spring框架。所以我用这样替换textarea:

function sanitize(text){
    var sanitized = text.replace("<script>", "");
    sanitized = sanitized.replace("</script>", "");
    return sanitized;
}

这与一些后端Java验证相结合,最终成为一个更清洁的解决方案。

但是如果你想要一个非弹簧/速度解决方案,那么下面的方法就可以了。

我拼凑了一个快速修复,因为我的主要目的是消除其他人轻松执行脚本的能力。这并不理想,我并没有声称它是最好的答案,所以如果有人找到更好的解决方案,请分享。我创造了一个&#34;消毒&#34;功能如下:

$(".main").on("keyup", "#actualTextArea", function () {
    var textAreaMarkup = $('#actualTextArea').val();
    var sanitizedMarkup = sanitize(textAreaMarkup );
    $('#actualTextArea').val(sanitizedMarkup);
    $('#previewTextArea').html(sanitizedMarkup);
});

 // This one can remain unchanged and infact needs to be
 // If it's the same as above it will wipe the text area
 //  on a highlight-backspace
$(".main").on("keydown", "#actualTextArea", function () {
    $('#previewTextArea').html($('#actualTextArea').val());
});

然后前两个事件处理程序现在看起来像:

AudioBufferSourceNode

除了Java端卫生以防止存储在数据库中的任何有害物质外,这符合我的目的,但如果它存在,我会对更好的解决方案持开放态度。