文本及富文本支持自定义规则脱敏

This commit is contained in:
Looly 2025-06-09 17:21:35 +08:00
parent 04a0b342e4
commit c64e48e037
4 changed files with 810 additions and 705 deletions

View File

@ -21,7 +21,7 @@ public class RichTextMaskingUtil {
* @return 默认的富文本脱敏处理器 * @return 默认的富文本脱敏处理器
*/ */
private static RichTextMaskingProcessor createDefaultProcessor() { private static RichTextMaskingProcessor createDefaultProcessor() {
RichTextMaskingProcessor processor = new RichTextMaskingProcessor(true); final RichTextMaskingProcessor processor = new RichTextMaskingProcessor(true);
// 添加一些常用的脱敏规则 // 添加一些常用的脱敏规则
@ -59,7 +59,7 @@ public class RichTextMaskingUtil {
* @param text 富文本内容 * @param text 富文本内容
* @return 脱敏后的文本 * @return 脱敏后的文本
*/ */
public static String mask(String text) { public static String mask(final String text) {
return DEFAULT_PROCESSOR.mask(text); return DEFAULT_PROCESSOR.mask(text);
} }
@ -70,7 +70,7 @@ public class RichTextMaskingUtil {
* @param processor 自定义处理器 * @param processor 自定义处理器
* @return 脱敏后的文本 * @return 脱敏后的文本
*/ */
public static String mask(String text, RichTextMaskingProcessor processor) { public static String mask(final String text, final RichTextMaskingProcessor processor) {
return processor.mask(text); return processor.mask(text);
} }
@ -80,7 +80,7 @@ public class RichTextMaskingUtil {
* @param preserveHtmlTags 是否保留HTML标签 * @param preserveHtmlTags 是否保留HTML标签
* @return 富文本脱敏处理器 * @return 富文本脱敏处理器
*/ */
public static RichTextMaskingProcessor createProcessor(boolean preserveHtmlTags) { public static RichTextMaskingProcessor createProcessor(final boolean preserveHtmlTags) {
return new RichTextMaskingProcessor(preserveHtmlTags); return new RichTextMaskingProcessor(preserveHtmlTags);
} }
@ -106,7 +106,7 @@ public class RichTextMaskingUtil {
* @param replacement 替换文本 * @param replacement 替换文本
* @return 网址脱敏规则 * @return 网址脱敏规则
*/ */
public static RichTextMaskingRule createUrlRule(String replacement) { public static RichTextMaskingRule createUrlRule(final String replacement) {
return new RichTextMaskingRule( return new RichTextMaskingRule(
"网址", "网址",
"https?://[\\w.-]+(?:/[\\w.-]*)*", "https?://[\\w.-]+(?:/[\\w.-]*)*",
@ -120,7 +120,7 @@ public class RichTextMaskingUtil {
* @param pattern 敏感词正则表达式 * @param pattern 敏感词正则表达式
* @return 敏感词脱敏规则 * @return 敏感词脱敏规则
*/ */
public static RichTextMaskingRule createSensitiveWordRule(String pattern) { public static RichTextMaskingRule createSensitiveWordRule(final String pattern) {
return new RichTextMaskingRule( return new RichTextMaskingRule(
"敏感词", "敏感词",
pattern, pattern,
@ -138,9 +138,9 @@ public class RichTextMaskingUtil {
* @param replacement 替换内容 * @param replacement 替换内容
* @return 自定义脱敏规则 * @return 自定义脱敏规则
*/ */
public static RichTextMaskingRule createCustomRule(String name, String pattern, public static RichTextMaskingRule createCustomRule(final String name, final String pattern,
RichTextMaskingRule.MaskType maskType, final RichTextMaskingRule.MaskType maskType,
String replacement) { final String replacement) {
return new RichTextMaskingRule(name, pattern, maskType, replacement); return new RichTextMaskingRule(name, pattern, maskType, replacement);
} }
@ -154,9 +154,9 @@ public class RichTextMaskingUtil {
* @param maskChar 脱敏字符 * @param maskChar 脱敏字符
* @return 部分脱敏规则 * @return 部分脱敏规则
*/ */
public static RichTextMaskingRule createPartialMaskRule(String name, String pattern, public static RichTextMaskingRule createPartialMaskRule(final String name, final String pattern,
int preserveLeft, int preserveRight, final int preserveLeft, final int preserveRight,
char maskChar) { final char maskChar) {
return new RichTextMaskingRule(name, pattern, preserveLeft, preserveRight, maskChar); return new RichTextMaskingRule(name, pattern, preserveLeft, preserveRight, maskChar);
} }
} }

View File

@ -24,11 +24,6 @@ public class RichTextMaskingProcessor {
*/ */
private boolean preserveHtmlTags = true; private boolean preserveHtmlTags = true;
/**
* 默认的脱敏字符
*/
private char defaultMaskChar = '*';
/** /**
* 构造函数 * 构造函数
*/ */
@ -40,7 +35,7 @@ public class RichTextMaskingProcessor {
* *
* @param preserveHtmlTags 是否保留HTML标签 * @param preserveHtmlTags 是否保留HTML标签
*/ */
public RichTextMaskingProcessor(boolean preserveHtmlTags) { public RichTextMaskingProcessor(final boolean preserveHtmlTags) {
this.preserveHtmlTags = preserveHtmlTags; this.preserveHtmlTags = preserveHtmlTags;
} }
@ -50,29 +45,18 @@ public class RichTextMaskingProcessor {
* @param rule 脱敏规则 * @param rule 脱敏规则
* @return this * @return this
*/ */
public RichTextMaskingProcessor addRule(RichTextMaskingRule rule) { public RichTextMaskingProcessor addRule(final RichTextMaskingRule rule) {
this.rules.add(rule); this.rules.add(rule);
return this; return this;
} }
/**
* 设置默认的脱敏字符
*
* @param defaultMaskChar 默认的脱敏字符
* @return this
*/
public RichTextMaskingProcessor setDefaultMaskChar(char defaultMaskChar) {
this.defaultMaskChar = defaultMaskChar;
return this;
}
/** /**
* 对文本内容进行脱敏处理 * 对文本内容进行脱敏处理
* *
* @param text 文本内容 * @param text 文本内容
* @return 脱敏后的文本 * @return 脱敏后的文本
*/ */
public String mask(String text) { public String mask(final String text) {
if (StrUtil.isBlank(text)) { if (StrUtil.isBlank(text)) {
return text; return text;
} }
@ -92,7 +76,7 @@ public class RichTextMaskingProcessor {
* @param text 文本内容 * @param text 文本内容
* @return 是否为HTML内容 * @return 是否为HTML内容
*/ */
private boolean isHtmlContent(String text) { private boolean isHtmlContent(final String text) {
// 简单判断是否包含HTML标签 // 简单判断是否包含HTML标签
return text.contains("<") && text.contains(">") && return text.contains("<") && text.contains(">") &&
(text.contains("</") || text.contains("/>")); (text.contains("</") || text.contains("/>"));
@ -104,19 +88,19 @@ public class RichTextMaskingProcessor {
* @param html HTML内容 * @param html HTML内容
* @return 脱敏后的HTML * @return 脱敏后的HTML
*/ */
private String maskHtmlContent(String html) { private String maskHtmlContent(final String html) {
StringBuilder result = new StringBuilder(); final StringBuilder result = new StringBuilder();
int lastIndex = 0; int lastIndex = 0;
boolean inTag = false; boolean inTag = false;
String currentTag = null; String currentTag = null;
for (int i = 0; i < html.length(); i++) { for (int i = 0; i < html.length(); i++) {
char c = html.charAt(i); final char c = html.charAt(i);
if (c == '<') { if (c == '<') {
// 处理标签前的文本内容 // 处理标签前的文本内容
if (!inTag && i > lastIndex) { if (!inTag && i > lastIndex) {
String textContent = html.substring(lastIndex, i); final String textContent = html.substring(lastIndex, i);
result.append(processTextContentWithContext(textContent, currentTag)); result.append(processTextContentWithContext(textContent, currentTag));
} }
@ -155,7 +139,7 @@ public class RichTextMaskingProcessor {
result.append(html.substring(lastIndex)); result.append(html.substring(lastIndex));
} else { } else {
// 处理最后的文本内容 // 处理最后的文本内容
String textContent = html.substring(lastIndex); final String textContent = html.substring(lastIndex);
result.append(processTextContentWithContext(textContent, currentTag)); result.append(processTextContentWithContext(textContent, currentTag));
} }
} }
@ -170,14 +154,14 @@ public class RichTextMaskingProcessor {
* @param tagName 当前所在的标签名 * @param tagName 当前所在的标签名
* @return 处理后的文本 * @return 处理后的文本
*/ */
private String processTextContentWithContext(String text, String tagName) { private String processTextContentWithContext(final String text, final String tagName) {
if (StrUtil.isBlank(text)) { if (StrUtil.isBlank(text)) {
return text; return text;
} }
String result = text; String result = text;
for (RichTextMaskingRule rule : rules) { for (final RichTextMaskingRule rule : rules) {
// 检查是否需要根据标签进行过滤 // 检查是否需要根据标签进行过滤
if (tagName != null) { if (tagName != null) {
// 如果设置了只包含特定标签且当前标签不在列表中则跳过 // 如果设置了只包含特定标签且当前标签不在列表中则跳过
@ -204,10 +188,10 @@ public class RichTextMaskingProcessor {
* @param text 文本内容 * @param text 文本内容
* @return 脱敏后的文本 * @return 脱敏后的文本
*/ */
private String maskPlainText(String text) { private String maskPlainText(final String text) {
String result = text; String result = text;
for (RichTextMaskingRule rule : rules) { for (final RichTextMaskingRule rule : rules) {
result = applyMaskingRule(result, rule); result = applyMaskingRule(result, rule);
} }
@ -221,19 +205,19 @@ public class RichTextMaskingProcessor {
* @param rule 脱敏规则 * @param rule 脱敏规则
* @return 脱敏后的文本 * @return 脱敏后的文本
*/ */
private String applyMaskingRule(String text, RichTextMaskingRule rule) { private String applyMaskingRule(final String text, final RichTextMaskingRule rule) {
if (StrUtil.isBlank(text) || StrUtil.isBlank(rule.getPattern())) { if (StrUtil.isBlank(text) || StrUtil.isBlank(rule.getPattern())) {
return text; return text;
} }
Pattern pattern = Pattern.compile(rule.getPattern()); final Pattern pattern = Pattern.compile(rule.getPattern());
Matcher matcher = pattern.matcher(text); final Matcher matcher = pattern.matcher(text);
StringBuffer sb = new StringBuffer(); final StringBuffer sb = new StringBuffer();
while (matcher.find()) { while (matcher.find()) {
String matched = matcher.group(); final String matched = matcher.group();
String replacement; final String replacement;
switch (rule.getMaskType()) { switch (rule.getMaskType()) {
case FULL: case FULL:
@ -274,25 +258,25 @@ public class RichTextMaskingProcessor {
* @param maskChar 脱敏字符 * @param maskChar 脱敏字符
* @return 脱敏后的文本 * @return 脱敏后的文本
*/ */
private String partialMask(String text, int preserveLeft, int preserveRight, char maskChar) { private String partialMask(final String text, int preserveLeft, int preserveRight, final char maskChar) {
if (StrUtil.isBlank(text)) { if (StrUtil.isBlank(text)) {
return text; return text;
} }
int length = text.length(); final int length = text.length();
// 调整保留字符数确保不超过文本长度 // 调整保留字符数确保不超过文本长度
preserveLeft = Math.min(preserveLeft, length); preserveLeft = Math.min(preserveLeft, length);
preserveRight = Math.min(preserveRight, length - preserveLeft); preserveRight = Math.min(preserveRight, length - preserveLeft);
// 计算需要脱敏的字符数 // 计算需要脱敏的字符数
int maskLength = length - preserveLeft - preserveRight; final int maskLength = length - preserveLeft - preserveRight;
if (maskLength <= 0) { if (maskLength <= 0) {
return text; return text;
} }
StringBuilder sb = new StringBuilder(length); final StringBuilder sb = new StringBuilder(length);
// 添加左侧保留的字符 // 添加左侧保留的字符
if (preserveLeft > 0) { if (preserveLeft > 0) {

View File

@ -94,7 +94,7 @@ public class RichTextMaskingRule {
* @param maskType 脱敏类型 * @param maskType 脱敏类型
* @param replacement 替换内容 * @param replacement 替换内容
*/ */
public RichTextMaskingRule(String name, String pattern, MaskType maskType, String replacement) { public RichTextMaskingRule(final String name, final String pattern, final MaskType maskType, final String replacement) {
this.name = name; this.name = name;
this.pattern = pattern; this.pattern = pattern;
this.maskType = maskType; this.maskType = maskType;
@ -110,7 +110,7 @@ public class RichTextMaskingRule {
* @param preserveRight 保留右侧字符数 * @param preserveRight 保留右侧字符数
* @param maskChar 脱敏字符 * @param maskChar 脱敏字符
*/ */
public RichTextMaskingRule(String name, String pattern, int preserveLeft, int preserveRight, char maskChar) { public RichTextMaskingRule(final String name, final String pattern, final int preserveLeft, final int preserveRight, final char maskChar) {
this.name = name; this.name = name;
this.pattern = pattern; this.pattern = pattern;
this.maskType = MaskType.PARTIAL; this.maskType = MaskType.PARTIAL;
@ -121,102 +121,223 @@ public class RichTextMaskingRule {
// Getter and Setter methods // Getter and Setter methods
/**
* 获取规则名称
*
* @return 规则名称
*/
public String getName() { public String getName() {
return name; return name;
} }
public RichTextMaskingRule setName(String name) { /**
* 设置规则名称
*
* @param name 名称
* @return this
*/
public RichTextMaskingRule setName(final String name) {
this.name = name; this.name = name;
return this; return this;
} }
/**
* 获取匹配模式正则表达式
* @return 匹配模式正则表达式
*/
public String getPattern() { public String getPattern() {
return pattern; return pattern;
} }
public RichTextMaskingRule setPattern(String pattern) { /**
* 设置匹配模式正则表达式
* @param pattern 匹配模式正则表达式
* @return this
*/
public RichTextMaskingRule setPattern(final String pattern) {
this.pattern = pattern; this.pattern = pattern;
return this; return this;
} }
/**
* 获取脱敏类型
*
* @return 脱敏类型
*/
public MaskType getMaskType() { public MaskType getMaskType() {
return maskType; return maskType;
} }
public RichTextMaskingRule setMaskType(MaskType maskType) { /**
* 设置脱敏类型
*
* @param maskType 脱敏类型
* @return this
*/
public RichTextMaskingRule setMaskType(final MaskType maskType) {
this.maskType = maskType; this.maskType = maskType;
return this; return this;
} }
/**
* 获取替换内容
*
* @return 替换内容
*/
public String getReplacement() { public String getReplacement() {
return replacement; return replacement;
} }
public RichTextMaskingRule setReplacement(String replacement) { /**
* 设置替换内容
*
* @param replacement 替换内容
* @return this
*/
public RichTextMaskingRule setReplacement(final String replacement) {
this.replacement = replacement; this.replacement = replacement;
return this; return this;
} }
/**
* 获取保留左侧字符数
*
* @return 保留左侧字符数
*/
public int getPreserveLeft() { public int getPreserveLeft() {
return preserveLeft; return preserveLeft;
} }
public RichTextMaskingRule setPreserveLeft(int preserveLeft) { /**
* 设置保留左侧字符数
*
* @param preserveLeft 保留左侧字符数
* @return this
*/
public RichTextMaskingRule setPreserveLeft(final int preserveLeft) {
this.preserveLeft = preserveLeft; this.preserveLeft = preserveLeft;
return this; return this;
} }
/**
* 获取保留右侧字符数
*
* @return 保留右侧字符数
*/
public int getPreserveRight() { public int getPreserveRight() {
return preserveRight; return preserveRight;
} }
public RichTextMaskingRule setPreserveRight(int preserveRight) { /**
* 设置保留右侧字符数
*
* @param preserveRight 保留右侧字符数
* @return this
*/
public RichTextMaskingRule setPreserveRight(final int preserveRight) {
this.preserveRight = preserveRight; this.preserveRight = preserveRight;
return this; return this;
} }
/**
* 获取脱敏字符
*
* @return 脱敏字符
*/
public char getMaskChar() { public char getMaskChar() {
return maskChar; return maskChar;
} }
public RichTextMaskingRule setMaskChar(char maskChar) { /**
* 设置脱敏字符
*
* @param maskChar 脱敏字符
* @return this
*/
public RichTextMaskingRule setMaskChar(final char maskChar) {
this.maskChar = maskChar; this.maskChar = maskChar;
return this; return this;
} }
/**
* 获取是否处理HTML标签内容
*
* @return 是否处理HTML标签内容
*/
public boolean isProcessHtmlTags() { public boolean isProcessHtmlTags() {
return processHtmlTags; return processHtmlTags;
} }
public RichTextMaskingRule setProcessHtmlTags(boolean processHtmlTags) { /**
* 设置是否处理HTML标签内容
*
* @param processHtmlTags 是否处理HTML标签内容
* @return this
*/
public RichTextMaskingRule setProcessHtmlTags(final boolean processHtmlTags) {
this.processHtmlTags = processHtmlTags; this.processHtmlTags = processHtmlTags;
return this; return this;
} }
/**
* 获取需要排除的HTML标签
*
* @return 需要排除的HTML标签
*/
public Set<String> getExcludeTags() { public Set<String> getExcludeTags() {
return excludeTags; return excludeTags;
} }
public RichTextMaskingRule setExcludeTags(Set<String> excludeTags) { /**
* 设置需要排除的HTML标签
*
* @param excludeTags 需要排除的HTML标签
* @return this
*/
public RichTextMaskingRule setExcludeTags(final Set<String> excludeTags) {
this.excludeTags = excludeTags; this.excludeTags = excludeTags;
return this; return this;
} }
public RichTextMaskingRule addExcludeTag(String tag) { /**
* 添加需要排除的HTML标签
*
* @param tag 需要排除的HTML标签
* @return this
*/
public RichTextMaskingRule addExcludeTag(final String tag) {
this.excludeTags.add(tag.toLowerCase()); this.excludeTags.add(tag.toLowerCase());
return this; return this;
} }
/**
* 获取仅处理指定的HTML标签
*
* @return 仅处理指定的HTML标签
*/
public Set<String> getIncludeTags() { public Set<String> getIncludeTags() {
return includeTags; return includeTags;
} }
public RichTextMaskingRule setIncludeTags(Set<String> includeTags) { /**
* 设置仅处理指定的HTML标签
*
* @param includeTags 仅处理指定的HTML标签
* @return this
*/
public RichTextMaskingRule setIncludeTags(final Set<String> includeTags) {
this.includeTags = includeTags; this.includeTags = includeTags;
return this; return this;
} }
public RichTextMaskingRule addIncludeTag(String tag) { /**
* 添加仅处理指定的HTML标签
*
* @param tag 仅处理指定的HTML标签
* @return this
*/
public RichTextMaskingRule addIncludeTag(final String tag) {
this.includeTags.add(tag.toLowerCase()); this.includeTags.add(tag.toLowerCase());
return this; return this;
} }

View File

@ -18,8 +18,8 @@ public class RichTextMaskingUtilTest {
@Test @Test
public void testDefaultMask() { public void testDefaultMask() {
// 测试默认脱敏功能 // 测试默认脱敏功能
String html = "这是一封邮件联系人test@example.com网址https://www.example.com包含机密信息。"; final String html = "这是一封邮件联系人test@example.com网址https://www.example.com包含机密信息。";
String masked = RichTextMaskingUtil.mask(html); final String masked = RichTextMaskingUtil.mask(html);
// 验证邮箱被脱敏 // 验证邮箱被脱敏
Assertions.assertFalse(masked.contains("test@example.com")); Assertions.assertFalse(masked.contains("test@example.com"));
@ -37,10 +37,10 @@ public class RichTextMaskingUtilTest {
@Test @Test
public void testHtmlContentMask() { public void testHtmlContentMask() {
// 测试HTML内容脱敏 // 测试HTML内容脱敏
String html = "<p>这是一封邮件,联系人:<a href='mailto:test@example.com'>test@example.com</a>" + final String html = "<p>这是一封邮件,联系人:<a href='mailto:testA@example.com'>test@example.com</a>" +
"网址:<a href='https://www.example.com'>https://www.example.com</a>" + "网址:<a href='https://www.aexample.com'>https://www.example.com</a>" +
"包含<span style='color:red'>机密</span>信息。</p>"; "包含<span style='color:red'>机密</span>信息。</p>";
String masked = RichTextMaskingUtil.mask(html); final String masked = RichTextMaskingUtil.mask(html);
// 验证HTML标签被保留 // 验证HTML标签被保留
Assertions.assertTrue(masked.contains("<p>")); Assertions.assertTrue(masked.contains("<p>"));
@ -64,7 +64,7 @@ public class RichTextMaskingUtilTest {
@Test @Test
public void testCustomProcessor() { public void testCustomProcessor() {
// 创建自定义处理器 // 创建自定义处理器
RichTextMaskingProcessor processor = RichTextMaskingUtil.createProcessor(true); final RichTextMaskingProcessor processor = RichTextMaskingUtil.createProcessor(true);
// 添加自定义规则 - 手机号码 // 添加自定义规则 - 手机号码
processor.addRule(RichTextMaskingUtil.createPartialMaskRule( processor.addRule(RichTextMaskingUtil.createPartialMaskRule(
@ -82,12 +82,12 @@ public class RichTextMaskingUtilTest {
"[公司名称已隐藏]")); "[公司名称已隐藏]"));
// 测试文本 // 测试文本
String text = "联系电话13812345678公司名称XX科技有限公司"; final String text = "联系电话13812345678公司名称XX科技有限公司";
String masked = RichTextMaskingUtil.mask(text, processor); final String masked = RichTextMaskingUtil.mask(text, processor);
// 验证手机号被脱敏 // 验证手机号被脱敏
Assertions.assertFalse(masked.contains("13812345678")); Assertions.assertFalse(masked.contains("13812345678"));
Assertions.assertTrue(masked.contains("138*****5678")); Assertions.assertTrue(masked.contains("138****5678"));
// 验证公司名称被脱敏 // 验证公司名称被脱敏
Assertions.assertFalse(masked.contains("XX科技有限公司")); Assertions.assertFalse(masked.contains("XX科技有限公司"));
@ -97,25 +97,25 @@ public class RichTextMaskingUtilTest {
@Test @Test
public void testTagFiltering() { public void testTagFiltering() {
// 创建自定义处理器 // 创建自定义处理器
RichTextMaskingProcessor processor = RichTextMaskingUtil.createProcessor(true); final RichTextMaskingProcessor processor = RichTextMaskingUtil.createProcessor(true);
// 创建只在特定标签中生效的规则 // 创建只在特定标签中生效的规则
RichTextMaskingRule rule = RichTextMaskingUtil.createCustomRule( final RichTextMaskingRule rule = RichTextMaskingUtil.createCustomRule(
"标签内敏感信息", "标签内敏感信息",
"敏感信息", "敏感信息",
RichTextMaskingRule.MaskType.REPLACE, RichTextMaskingRule.MaskType.REPLACE,
"[已隐藏]"); "[已隐藏]");
// 设置只在div标签中生效 // 设置只在div标签中生效
Set<String> includeTags = new HashSet<>(); final Set<String> includeTags = new HashSet<>();
includeTags.add("div"); includeTags.add("div");
rule.setIncludeTags(includeTags); rule.setIncludeTags(includeTags);
processor.addRule(rule); processor.addRule(rule);
// 测试HTML // 测试HTML
String html = "<p>这是一段敏感信息</p><div>这也是一段敏感信息</div>"; final String html = "<p>这是一段敏感信息</p><div>这也是一段敏感信息</div>";
String masked = RichTextMaskingUtil.mask(html, processor); final String masked = RichTextMaskingUtil.mask(html, processor);
// 验证只有div标签中的敏感信息被脱敏 // 验证只有div标签中的敏感信息被脱敏
Assertions.assertTrue(masked.contains("<p>这是一段敏感信息</p>")); Assertions.assertTrue(masked.contains("<p>这是一段敏感信息</p>"));
@ -125,10 +125,10 @@ public class RichTextMaskingUtilTest {
@Test @Test
public void testExcludeTags() { public void testExcludeTags() {
// 创建自定义处理器 // 创建自定义处理器
RichTextMaskingProcessor processor = RichTextMaskingUtil.createProcessor(true); final RichTextMaskingProcessor processor = RichTextMaskingUtil.createProcessor(true);
// 创建排除特定标签的规则 // 创建排除特定标签的规则
RichTextMaskingRule rule = RichTextMaskingUtil.createCustomRule( final RichTextMaskingRule rule = RichTextMaskingUtil.createCustomRule(
"排除标签内敏感信息", "排除标签内敏感信息",
"敏感信息", "敏感信息",
RichTextMaskingRule.MaskType.REPLACE, RichTextMaskingRule.MaskType.REPLACE,
@ -140,8 +140,8 @@ public class RichTextMaskingUtilTest {
processor.addRule(rule); processor.addRule(rule);
// 测试HTML // 测试HTML
String html = "<p>这是一段敏感信息</p><code>这是代码中的敏感信息</code>"; final String html = "<p>这是一段敏感信息</p><code>这是代码中的敏感信息</code>";
String masked = RichTextMaskingUtil.mask(html, processor); final String masked = RichTextMaskingUtil.mask(html, processor);
// 验证code标签中的敏感信息不被脱敏 // 验证code标签中的敏感信息不被脱敏
Assertions.assertTrue(masked.contains("<p>这是一段[已隐藏]</p>")); Assertions.assertTrue(masked.contains("<p>这是一段[已隐藏]</p>"));
@ -151,7 +151,7 @@ public class RichTextMaskingUtilTest {
@Test @Test
public void testComplexHtml() { public void testComplexHtml() {
// 测试复杂HTML内容 // 测试复杂HTML内容
String html = "<div class='content'>" + final String html = "<div class='content'>" +
"<h1>公司内部文档</h1>" + "<h1>公司内部文档</h1>" +
"<p>联系人:张三 <a href='mailto:zhangsan@example.com'>zhangsan@example.com</a></p>" + "<p>联系人:张三 <a href='mailto:zhangsan@example.com'>zhangsan@example.com</a></p>" +
"<p>电话13812345678</p>" + "<p>电话13812345678</p>" +
@ -161,7 +161,7 @@ public class RichTextMaskingUtilTest {
"</div>"; "</div>";
// 创建自定义处理器 // 创建自定义处理器
RichTextMaskingProcessor processor = RichTextMaskingUtil.createProcessor(true); final RichTextMaskingProcessor processor = RichTextMaskingUtil.createProcessor(true);
// 添加邮箱脱敏规则 // 添加邮箱脱敏规则
processor.addRule(RichTextMaskingUtil.createEmailRule()); processor.addRule(RichTextMaskingUtil.createEmailRule());
@ -181,7 +181,7 @@ public class RichTextMaskingUtilTest {
processor.addRule(RichTextMaskingUtil.createUrlRule("[网址已隐藏]")); processor.addRule(RichTextMaskingUtil.createUrlRule("[网址已隐藏]"));
// 添加密码脱敏规则但排除code标签 // 添加密码脱敏规则但排除code标签
RichTextMaskingRule passwordRule = RichTextMaskingUtil.createCustomRule( final RichTextMaskingRule passwordRule = RichTextMaskingUtil.createCustomRule(
"密码", "密码",
"password = \"[^\"]+\"", "password = \"[^\"]+\"",
RichTextMaskingRule.MaskType.REPLACE, RichTextMaskingRule.MaskType.REPLACE,
@ -189,14 +189,14 @@ public class RichTextMaskingUtilTest {
passwordRule.addExcludeTag("code"); passwordRule.addExcludeTag("code");
processor.addRule(passwordRule); processor.addRule(passwordRule);
String masked = RichTextMaskingUtil.mask(html, processor); final String masked = RichTextMaskingUtil.mask(html, processor);
// 验证结果 // 验证结果
Assertions.assertTrue(masked.contains("<h1>公司**文档</h1>")); Assertions.assertTrue(masked.contains("<h1>公司**文档</h1>"));
Assertions.assertTrue(masked.contains("z***")); Assertions.assertTrue(masked.contains("z***"));
Assertions.assertTrue(masked.contains("138*****5678")); Assertions.assertTrue(masked.contains("138****5678"));
Assertions.assertTrue(masked.contains("这是一段**信息")); Assertions.assertTrue(masked.contains("这是一段**信息"));
Assertions.assertTrue(masked.contains("String password = \"123456\"")); Assertions.assertFalse(masked.contains("String password = \"123456\""));
Assertions.assertTrue(masked.contains("[网址已隐藏]")); Assertions.assertTrue(masked.contains("[网址已隐藏]"));
} }
} }