使用OWASP Java HTML Sanitizer为每个h2标签添加唯一属性ID。

5
我将使用owasp-java-html-sanitizer,并尝试为我的HTML代码中的每个h2标签添加id属性,该属性应在多个页面加载之间保持不变,但对于页面上的每个元素都是唯一的(如id属性定义)。我尝试计算所有元素以获取索引,并将索引添加到每个h2元素中。但是,在Java中的此时点我无法访问此数据。然后我使用了UUID.randomUUID(),但由于它是随机的,因此id不是持久的。
以下是我当前拥有的代码:
public PolicyFactory HtmlPolicy() {
    return new HtmlPolicyBuilder()
        .allowElements("h3", "h4", "h5", "h6", "p", "span", "br", "b", "strong", "i", "em", "u", "hr", "ol", "ul", "li",
                       "img", "table", "tr", "th", "td", "thead", "tbody", "tfoot", "caption", "colgroup", "col", "blockquote", "figure", "figcaption", "object", "iframe")
        .allowElements(
            (String elementName, List<String> attrs) -> {
                String uniqueID = UUID.randomUUID().toString();
                // Add an attribute.
                attrs.add("id");                
                attrs.add("headline-" + uniqueID);
                attrs.add("class");
                attrs.add("scrollspy");
               // Return elementName to include, null to drop.
               return elementName;
            }, "h2")
        .toFactory();
}

在JavaScript中,我会这样做:

        $('h2').each(function(index, obj) {
            let newObj = $(obj)[0];
            $(newObj).attr('id', `headline-2-${index + 1}`);
        });

有没有一种方法可以在这种情况下将每个 h2 元素的值增加 1?


重新考虑必要性,因为您可以使用 h2:nth-of-type(index) 来在客户端上定位 H2。 - Christoph Dahlen
我的初始方案是通过 javascript 在客户端添加 id。然而,在 Google 搜索结果中,它们直接深度链接到 h2-headline。如果我使用 javascript 添加 id,则 Google 的深度链接将无法正常工作。 - Nixen85
你不能从h2中读取attrs的值并使用它来构建唯一的id吗? - morganney
2个回答

0

我不知道 owasp-java-html-sanitizer,但我认为你可以使用额外的变量来存储已使用 ID 的索引 - 比如 AtomicInteger。 对于你的代码,它可能看起来像这样:

public PolicyFactory HtmlPolicy() {
    AtomicInteger index = new AtomicInteger();
    return new HtmlPolicyBuilder()
        .allowElements("h3", "h4", "h5", "h6", "p", "span", "br", "b", "strong", "i", "em", "u", "hr", "ol", "ul", "li",
                       "img", "table", "tr", "th", "td", "thead", "tbody", "tfoot", "caption", "colgroup", "col", "blockquote", "figure", "figcaption", "object", "iframe")
        .allowElements(
            (String elementName, List<String> attrs) -> {
                // Add an attribute.
                attrs.add("id");                
                attrs.add("headline-" + index.incrementAndGet());
                attrs.add("class");
                attrs.add("scrollspy");
               // Return elementName to include, null to drop.
               return elementName;
            }, "h2")
        .toFactory();
}

这个想法基本上是正确的,但它会在页面会话中增加整数,也就是说对于一个初始页面加载有5个标题的页面,第一个h2被标记为headline-1,而对于第二次页面加载来说它是第6个标题,对于第三次页面加载来说则是headline-11...必须保证跨页面加载时整数相等... - Nixen85
所以在某种程度上,当一页的内容被清理后,我需要重置计数器。 - Nixen85

0

@tchudyk 提供的解决方案可能可以正常工作:我不完全确定,因为 HtmlPolicyBuilder线程不安全的,而且我猜想该库是否会每次都保持对 H2 标题的迭代顺序。

作为另一种方法,考虑使用JSoup,它是一个 Java HTML 解析和操作库。

想法是使用 JSoup 操作您的 HTML,以在将其与 OWASP 进行消毒之前将必要的 id 属性包含在您的页面中。

例如,您可以提取 h2 标签,然后设置适当的 id 属性

String html = "...";
Document doc = Jsoup.parse(html);
Elements h2Tags = doc.select("h2"); // analogous to your example in JQuery
// Iterate, in a deterministic way, over results
int index = 0;
for (Element h2Tag : h2Tags) {
  h2Tag.attr("id", "headline-2-" + index++);
}
String transformedHtml = doc.outerHtml();

虽然我认为它比OWASP弱,但该库也提供了一些净化功能


谢谢。如果其他方法都不起作用,我会回来尝试你的解决方案! - Nixen85
不客气,@Nixen85。希望能对你有所帮助。 - jccampanero

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接