mirror of
https://gitee.com/dromara/RuoYi-Vue-Plus.git
synced 2026-09-18 17:38:48 +08:00
Pre Merge pull request !742 from AprilWind/dev-xss1
This commit is contained in:
commit
af8f9f385a
7
pom.xml
7
pom.xml
@ -36,6 +36,7 @@
|
||||
<mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version>
|
||||
<lombok.version>1.18.38</lombok.version>
|
||||
<bouncycastle.version>1.80</bouncycastle.version>
|
||||
<owasp.html-sanitizer.version>20240325.1</owasp.html-sanitizer.version>
|
||||
<justauth.version>1.16.7</justauth.version>
|
||||
<!-- 离线IP地址定位库 -->
|
||||
<ip2region.version>2.7.0</ip2region.version>
|
||||
@ -288,6 +289,12 @@
|
||||
<version>${bouncycastle.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
|
||||
<artifactId>owasp-java-html-sanitizer</artifactId>
|
||||
<version>${owasp.html-sanitizer.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.github.linpeilie</groupId>
|
||||
<artifactId>mapstruct-plus-spring-boot-starter</artifactId>
|
||||
|
||||
@ -94,6 +94,11 @@
|
||||
<artifactId>ip2region</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
|
||||
<artifactId>owasp-java-html-sanitizer</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@ -0,0 +1,165 @@
|
||||
package org.dromara.common.core.utils;
|
||||
|
||||
import org.owasp.html.HtmlPolicyBuilder;
|
||||
import org.owasp.html.PolicyFactory;
|
||||
import org.owasp.html.Sanitizers;
|
||||
|
||||
/**
|
||||
* HTML/XSS 过滤工具类
|
||||
* 基于 OWASP Java HTML Sanitizer
|
||||
*
|
||||
* @author AprilWind
|
||||
*/
|
||||
public class HtmlSanitizerUtil {
|
||||
/**
|
||||
* 纯文本策略:
|
||||
* 去除所有 HTML 标签,仅保留纯文本内容,
|
||||
* 适用于对内容格式无任何要求,只需要纯文本的场景,如用户名、标题等
|
||||
*/
|
||||
public static final PolicyFactory TEXT_ONLY_POLICY = new HtmlPolicyBuilder().toFactory();
|
||||
|
||||
/**
|
||||
* 简单展示文本策略:
|
||||
* 允许部分格式化标签,介于纯文本和富文本之间,
|
||||
* 适用于简单文本展示,如昵称、简短描述等
|
||||
*/
|
||||
public static final PolicyFactory SIMPLE_TEXT_POLICY = Sanitizers.FORMATTING;
|
||||
|
||||
/**
|
||||
* 严格无脚本策略:
|
||||
* <p>
|
||||
* 仅允许非常基础的格式化标签,如加粗(b/strong)、斜体(i/em)、下划线(u)、
|
||||
* 段落(p)、换行(br)和列表(ul/ol/li)等,禁止所有标签属性,
|
||||
* 包括样式(style)、事件处理器(onXXX)或其他可能引入 XSS 的内容
|
||||
* </p>
|
||||
* <p>
|
||||
* 适用于对安全要求极高且不需要任何复杂格式的场景,
|
||||
* 如纯文本内容的最小格式化需求
|
||||
* </p>
|
||||
*/
|
||||
public static final PolicyFactory STRICT_NO_SCRIPT_POLICY = new HtmlPolicyBuilder()
|
||||
.allowElements("b", "strong", "i", "em", "u", "p", "br", "ul", "ol", "li")
|
||||
// 显式声明允许文本出现在这些标签中,增强策略清晰度(可选)
|
||||
.allowTextIn("b", "strong", "i", "em", "u", "p", "ul", "ol", "li")
|
||||
.toFactory();
|
||||
|
||||
/**
|
||||
* 评论区策略:
|
||||
* 允许基础格式化标签和超链接,
|
||||
* 防止图片、表格等复杂内容,
|
||||
* 适用于评论区文本,既保证安全,又支持简单的文本格式和链接
|
||||
*/
|
||||
public static final PolicyFactory COMMENT_POLICY = Sanitizers.FORMATTING
|
||||
.and(Sanitizers.LINKS);
|
||||
|
||||
/**
|
||||
* 文章编辑器策略:
|
||||
* 允许格式化标签、超链接、图片、样式、块级元素和表格,
|
||||
* 适用于富文本编辑器内容,如文章正文,兼顾内容丰富和安全
|
||||
*/
|
||||
public static final PolicyFactory ARTICLE_POLICY = Sanitizers.FORMATTING
|
||||
.and(Sanitizers.LINKS)
|
||||
.and(Sanitizers.IMAGES)
|
||||
.and(Sanitizers.STYLES)
|
||||
.and(Sanitizers.BLOCKS)
|
||||
.and(Sanitizers.TABLES);
|
||||
|
||||
/**
|
||||
* 富文本邮件内容策略:
|
||||
* 允许基础格式化标签、超链接、图片、表格和样式,
|
||||
* 相较于一般富文本编辑器稍微严格一些,主要用于邮件内容的安全过滤,
|
||||
* 防止恶意脚本注入,同时保证邮件内容的丰富展示效果
|
||||
*/
|
||||
public static final PolicyFactory EMAIL_HTML_POLICY = Sanitizers.FORMATTING
|
||||
.and(Sanitizers.LINKS)
|
||||
.and(Sanitizers.IMAGES)
|
||||
.and(Sanitizers.STYLES)
|
||||
.and(Sanitizers.TABLES);
|
||||
|
||||
/**
|
||||
* CMS 编辑器策略:较宽松,允许多种标签和属性
|
||||
*
|
||||
* <p>该策略适用于内容管理系统中的富文本编辑器,支持多样化的HTML标签和常用属性,
|
||||
* 包括超链接、图片、表格、媒体标签等,同时允许安全的样式和部分自定义属性。</p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>允许常见的结构化标签,如段落(p)、标题(h1-h6)、列表(ul,ol,li)、表格(table等)</li>
|
||||
* <li>支持超链接(a)的href属性,图片(img)的src、alt等属性</li>
|
||||
* <li>支持iframe、video、audio等媒体标签及其常用属性</li>
|
||||
* <li>允许表格单元格的合并属性colspan、rowspan</li>
|
||||
* <li>通过allowStyling方法,允许内联样式并进行安全过滤</li>
|
||||
* <li>限制URL协议为http、https和mailto,避免javascript等危险协议</li>
|
||||
* <li>支持部分常用的自定义数据属性(data-toggle、data-target、data-id)以便前端交互</li>
|
||||
* <li>支持无障碍相关的aria-*属性和role属性,提升辅助设备兼容性</li>
|
||||
* <li>允许iframe的特定属性allowfullscreen和frameborder以支持全屏和边框控制</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static final PolicyFactory CMS_EDITOR_POLICY = new HtmlPolicyBuilder()
|
||||
.allowElements(
|
||||
"a", "b", "blockquote", "br", "caption", "cite", "code",
|
||||
"col", "colgroup", "dd", "div", "dl", "dt", "em", "h1",
|
||||
"h2", "h3", "h4", "h5", "h6", "i", "img", "li", "ol",
|
||||
"p", "pre", "q", "small", "strike", "strong", "sub",
|
||||
"sup", "table", "tbody", "td", "tfoot", "th", "thead",
|
||||
"tr", "u", "ul", "span", "iframe", "video", "audio", "source")
|
||||
.allowAttributes("href").onElements("a")
|
||||
.allowAttributes("src", "alt", "title", "width", "height", "type", "controls").onElements("img", "iframe", "video", "audio", "source")
|
||||
.allowAttributes("colspan", "rowspan").onElements("td", "th")
|
||||
.allowStyling() // 允许安全的内联样式,过滤危险CSS
|
||||
.allowUrlProtocols("http", "https", "mailto") // 限制URL协议,防止注入javascript等
|
||||
.allowAttributes("data-toggle", "data-target", "data-id").onElements("*") // 支持部分自定义 data-* 属性,方便前端交互
|
||||
.allowAttributes("aria-label", "aria-hidden", "aria-expanded", "aria-pressed").onElements("*") // 支持无障碍辅助属性
|
||||
.allowAttributes("role").onElements("*") // 支持无障碍role属性
|
||||
.allowAttributes("allowfullscreen", "frameborder").onElements("iframe") // iframe 支持全屏及边框属性
|
||||
.toFactory();
|
||||
|
||||
/**
|
||||
* 纯文本过滤,去除所有 HTML 标签
|
||||
*/
|
||||
public static String sanitizeToText(String htmlContent) {
|
||||
return htmlContent == null ? null : TEXT_ONLY_POLICY.sanitize(htmlContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 简单文本过滤,允许部分格式
|
||||
*/
|
||||
public static String sanitizeForSimpleText(String htmlContent) {
|
||||
return htmlContent == null ? null : SIMPLE_TEXT_POLICY.sanitize(htmlContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 严格无脚本过滤,只允许非常基础标签,无任何属性
|
||||
*/
|
||||
public static String sanitizeStrictNoScript(String htmlContent) {
|
||||
return htmlContent == null ? null : STRICT_NO_SCRIPT_POLICY.sanitize(htmlContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 评论区 HTML 过滤
|
||||
*/
|
||||
public static String sanitizeForComment(String htmlContent) {
|
||||
return htmlContent == null ? null : COMMENT_POLICY.sanitize(htmlContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 文章编辑器 HTML 过滤
|
||||
*/
|
||||
public static String sanitizeForArticle(String htmlContent) {
|
||||
return htmlContent == null ? null : ARTICLE_POLICY.sanitize(htmlContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 邮件富文本过滤
|
||||
*/
|
||||
public static String sanitizeForEmailHtml(String htmlContent) {
|
||||
return htmlContent == null ? null : EMAIL_HTML_POLICY.sanitize(htmlContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* CMS 编辑器过滤,允许较多标签及属性
|
||||
*/
|
||||
public static String sanitizeForCmsEditor(String htmlContent) {
|
||||
return htmlContent == null ? null : CMS_EDITOR_POLICY.sanitize(htmlContent);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user