jsoup.clean 将单引号替换为双引号。我怎样才能防止这种情况发生?

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

对于我们的应用程序,我们允许用户输入 HTML,稍后会向其他用户显示。

出于安全原因,我们会清理此 HTML,并且不允许用户保存 HTML,这在其他用户浏览器中运行可能不安全。

为此,我们有这两种方法(简单来说,它们做得更多,但这就是这个问题的本质):

public static String sanitizeHTML(String html) {
        return Jsoup.clean(html,
                "",
                Safelist.relaxed()
                        .addAttributes(":all", "style")
                        .addAttributes(":all", "class"),
                new Document.OutputSettings().prettyPrint(false));
    }

    public static boolean isHTMLStringPolluted(String html) {
         return !sanitizeHTML(html).equals(html);
    }

我们使用

isHTMLStringPolluted
来验证用户输入。

如果用户现在输入

<a href="https://www.stackoverflow.com">Link</a>
,那完全没问题。 如果用户输入
<a href='https://www.stackoverflow.com'>Link</a>
,该方法将返回 false,因为 sanitizeHTML 方法返回
<a href="https://www.stackoverflow.com">Link</a>

这只是这个问题最简单的例子之一。用户可以添加更复杂的 HTML。此外,它们不仅有 HTML 编辑器,还可以通过非常复杂的数学语言(与 Excel 公式相当)创建、计算和连接这些 HTML 片段,该语言在整个应用程序中使用数据、变量和其他 HTML 输出。这个 HTML 只是结果。

我们不想强迫用户只使用双引号,我们也不希望用双引号替换单引号,以确保原始用户输入要么完全接受,要么完全拒绝。

有没有办法配置jsoup以保持报价的原样?

我还使用了不同的库,例如 OWASP Java HTML Sanitizer,但它有更多限制和缺陷,不符合我们的要求。

java html jsoup sanitization
1个回答
0
投票

jsoup 中没有设置会在属性值周围保留单引号。

我会以不同的方式处理这个问题 - 而不是尝试比较精确的输入和输出相等性,而是使用

Cleaner.isValidBodyHtml()
方法。检查输入的 HTML 是否不包含任何解析错误,并且 Cleaner 没有删除任何不在 Safelist 中的元素或属性。

无论该方法的输出如何,您都应该只使用/保留清理后的输出,而不是原始输入。

就我个人而言,我通常会使用

isValid()
作为 UI 指示器,而不是在其基础上进行阻塞——因为无论输入如何,清理后的输出都是安全的并且具有平衡的标签。没有理由阻止,例如只是因为用户错过了结束标签。但这种行为显然取决于您的具体用例。

这是一个有效的例子:

Safelist safelist = Safelist.relaxed()
    .addAttributes(":all", "style")
    .addAttributes(":all", "class");
Cleaner cleaner = new Cleaner(safelist);

String input = "<a href='https://www.stackoverflow.com'>Link</a>";
boolean isValid = cleaner.isValidBodyHtml(input);
print("isValid?", String.valueOf(isValid));

Document cleanDoc = cleaner.clean(Jsoup.parse(input));
print("Cleaned", cleanDoc.body().html());

给予:

isValid?: true
Cleaned: <a href="https://www.stackoverflow.com">Link</a>

还有

的输入
String input = 
 "<a href='https://www.stackoverflow.com' class=ok>Link<script>xss()</script>";

给予:

isValid?: false
Cleaned: <a href="https://www.stackoverflow.com" class="ok">Link</a>
© www.soinside.com 2019 - 2024. All rights reserved.