如何使实时 HTML 预览文本区域免受 HTML/脚本注入的影响

问题描述 投票:0回答:2

我转向这里作为最后的手段。我搜索了谷歌,但在找到解决方案时遇到了麻烦。我有一个带有 textarea 元素的表单,允许您在该区域中键入 html,如果您启用了预览模式,它将在您键入时实时呈现 HTML 标记。与 StackOverflow 在新帖子下方显示预览的方式没有太大不同。

但是,我最近发现我的功能存在漏洞。我所要做的就是输入如下内容:

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

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

我找到了这篇文章; 使用 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());
});

有没有办法可以重构它以使其安全?我目前唯一的想法是擦除实时预览并使用开关打开/关闭并对其进行编码,但我真的认为这是一个很酷的功能,并且希望保持它的实时状态而不是切换。有没有办法“实时编码”它或转义某些标签或其他东西?

javascript jquery html spring-mvc velocity
2个回答
0
投票

编辑:实际上,我认为这个解决方案更干净一些,并且使得下面的代码变得不必要。在速度页面中,所需要的只是利用 Spring 框架。所以我用这样替换文本区域:

#springBindEscaped("myJavaObj.textAreaText" true)
<textarea id="actualTextArea" name="${status.expression}" class="myClass" rows="10" cols="120">$!status.value</textarea>

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

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


我拼凑了一个快速修复程序,因为我的主要目的是消除其他人轻松执行脚本的能力。这并不理想,我并不是说它是最好的答案,所以如果有人找到更好的解决方案,请分享。我创建了一个“清理”功能,如下所示:

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

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

$(".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());
});

与 Java 端卫生一起防止任何有害内容存储在数据库中,这符合我的目的,但我非常愿意接受更好的解决方案(如果存在)。


0
投票

为了清理文本区域预览,只需将所有

<
>
替换为其等效的 html 字符代码:

function showPreview()
{
  var value = $('#writer').val().trim();
  value = value.replaceAll("<", "&lt;");
  value = value.replaceAll(">", "&gt;");
  $('#preview').html(value);
}
<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>

© www.soinside.com 2019 - 2024. All rights reserved.