69 lines
2.9 KiB
Java
69 lines
2.9 KiB
Java
package com.yunhai.svchall.utils;
|
||
|
||
import org.jsoup.Jsoup;
|
||
import org.jsoup.safety.Safelist;
|
||
|
||
import java.util.regex.Pattern;
|
||
|
||
/**
|
||
* 富文本白名单清洗(Cms HtmlSanitizer 原样平移:jsoup Safelist.relaxed() 基础 +
|
||
* figure/figcaption/span + 受限 style + a/img 协议收紧 + preserveRelativeLinks)。
|
||
* script/iframe/on* 一律剥除;列表页纯文本字段 th:text 等价转义,utext 仅限本工具清洗过的内容。
|
||
*/
|
||
public final class HtmlSanitizer {
|
||
|
||
/** 允许保留的内联样式属性(排版用途),其余 style 值丢弃 */
|
||
private static final Pattern SAFE_STYLE =
|
||
Pattern.compile("^(\\s*(text-align|color|background-color|font-size|font-weight"
|
||
+ "|line-height|width|height|max-width|float|margin|padding)\\s*:\\s*[^;()]+;?)*\\s*$",
|
||
Pattern.CASE_INSENSITIVE);
|
||
|
||
private static final Safelist WHITELIST = Safelist.relaxed()
|
||
.addTags("figure", "figcaption", "span")
|
||
.addAttributes(":all", "style")
|
||
.addAttributes("img", "style", "alt", "width", "height")
|
||
.addProtocols("a", "href", "http", "https", "mailto", "ftp", "#")
|
||
.addProtocols("img", "src", "http", "https", "data")
|
||
// 相对链接保留(Cms B-9 修复平移):上传地址相对路径入库,编辑器贴图 img src 即相对 URL
|
||
.preserveRelativeLinks(true);
|
||
|
||
private HtmlSanitizer() {
|
||
}
|
||
|
||
/**
|
||
* 清洗富文本;空入参原样返回。baseUri 用占位 https 域(Cms B-9 根因修复配套,
|
||
* 配合 preserveRelativeLinks(true) 回写原始相对值)。
|
||
*/
|
||
public static String clean(String html) {
|
||
if (html == null || html.isEmpty()) {
|
||
return html;
|
||
}
|
||
String cleaned = Jsoup.clean(html, "https://sanitizer.base.invalid/", WHITELIST);
|
||
return stripUnsafeStyle(cleaned);
|
||
}
|
||
|
||
/** 纯文本提取(摘要兜底/搜索片段用):去标签 + 折叠空白 */
|
||
public static String toText(String html, int maxLength) {
|
||
if (html == null || html.isEmpty()) {
|
||
return "";
|
||
}
|
||
String text = Jsoup.parse(html).text().replaceAll("\\s+", " ").trim();
|
||
if (maxLength > 0 && text.length() > maxLength) {
|
||
return text.substring(0, maxLength);
|
||
}
|
||
return text;
|
||
}
|
||
|
||
/** jsoup 不支持按值过滤属性,二次遍历按 SAFE_STYLE 白名单过滤 style(Cms A-07 修复平移) */
|
||
private static String stripUnsafeStyle(String html) {
|
||
org.jsoup.nodes.Document doc = org.jsoup.Jsoup.parseBodyFragment(html);
|
||
for (org.jsoup.nodes.Element el : doc.select("[style]")) {
|
||
String style = el.attr("style");
|
||
if (style == null || !SAFE_STYLE.matcher(style).matches()) {
|
||
el.removeAttr("style");
|
||
}
|
||
}
|
||
return doc.body().html();
|
||
}
|
||
}
|