This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user