mirror of
https://github.com/chillzhuang/blade-tool
synced 2025-04-12 07:47:22 +08:00
⚡ 新增脱敏工具类
This commit is contained in:
parent
61a4450d65
commit
940a120b8d
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.com).
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springblade.core.tool.sensitive;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 敏感信息处理配置类
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@Builder
|
||||
@Data
|
||||
public class SensitiveConfig {
|
||||
// 启用的内置正则脱敏类型
|
||||
private Set<SensitiveType> sensitiveTypes;
|
||||
|
||||
// 启用的内置敏感词分组
|
||||
private Set<SensitiveWord> sensitiveWords;
|
||||
|
||||
// 自定义敏感词列表
|
||||
private List<String> customSensitiveWords;
|
||||
|
||||
// 自定义正则表达式脱敏规则
|
||||
private Map<String, Pattern> customPatterns;
|
||||
|
||||
// 自定义替换文本(可选,有默认值)
|
||||
private String replacement;
|
||||
|
||||
// 是否按行处理
|
||||
private boolean processLineByLine;
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.com).
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springblade.core.tool.sensitive;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 脱敏类型枚举.
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@Getter
|
||||
public enum SensitiveType {
|
||||
GLOBAL("全局", "(.{2}).*(.{2})", "$1****$2"),
|
||||
MOBILE("手机号", "(\\d{3})\\d{4}(\\d{4})", "$1****$2"),
|
||||
EMAIL("电子邮箱", "(\\w{2})\\w+(@\\w+\\.\\w+)", "$1****$2"),
|
||||
ID_CARD("身份证号", "(\\d{4})\\d{10}(\\w{4})", "$1**********$2"),
|
||||
BANK_CARD("银行卡号", "(\\d{4})\\d+(\\d{4})", "$1****$2"),
|
||||
;
|
||||
|
||||
private final String desc;
|
||||
private final String regex;
|
||||
private final String replacement;
|
||||
|
||||
SensitiveType(String desc, String regex, String replacement) {
|
||||
this.desc = desc;
|
||||
this.regex = regex;
|
||||
this.replacement = replacement;
|
||||
}
|
||||
}
|
@ -0,0 +1,286 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.com).
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springblade.core.tool.sensitive;
|
||||
|
||||
import org.springblade.core.tool.utils.CollectionUtil;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 敏感信息处理工具类
|
||||
* <p>
|
||||
* 支持以下功能:
|
||||
* 1. 内置敏感类型处理(手机号、邮箱、身份证等)
|
||||
* 2. 自定义正则表达式处理
|
||||
* 3. 敏感词处理
|
||||
* 4. 支持按行处理或整体处理
|
||||
* 5. 支持自定义替换符
|
||||
* 6. 支持泛型返回值
|
||||
* </p>
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public class SensitiveUtil {
|
||||
private static final String DEFAULT_REPLACEMENT = "******";
|
||||
private static final String LINE_SEPARATOR = System.lineSeparator();
|
||||
|
||||
// 预编译的正则表达式
|
||||
private static final Map<SensitiveType, Pattern> PATTERN_CACHE = new EnumMap<>(SensitiveType.class);
|
||||
|
||||
// 预编译的默认配置
|
||||
private static final SensitiveConfig DEFAULT_CONFIG = SensitiveConfig.builder()
|
||||
.sensitiveTypes(EnumSet.of(
|
||||
SensitiveType.MOBILE,
|
||||
SensitiveType.ID_CARD,
|
||||
SensitiveType.EMAIL,
|
||||
SensitiveType.BANK_CARD
|
||||
))
|
||||
.sensitiveWords(EnumSet.of(
|
||||
SensitiveWord.SECURE,
|
||||
SensitiveWord.AUTHENTICATION
|
||||
))
|
||||
.processLineByLine(true)
|
||||
.replacement(DEFAULT_REPLACEMENT)
|
||||
.build();
|
||||
|
||||
static {
|
||||
// 预编译所有内置的正则表达式
|
||||
for (SensitiveType type : SensitiveType.values()) {
|
||||
PATTERN_CACHE.put(type, Pattern.compile(type.getRegex()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用默认配置处理敏感信息
|
||||
*
|
||||
* @param content 待处理内容
|
||||
* @return 处理后的结果
|
||||
*/
|
||||
public static String process(String content) {
|
||||
return process(content, DEFAULT_CONFIG);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用自定义配置处理敏感信息
|
||||
*
|
||||
* @param content 待处理内容
|
||||
* @param config 自定义配置
|
||||
* @return 处理后的结果
|
||||
*/
|
||||
public static String process(String content, SensitiveConfig config) {
|
||||
if (StringUtil.isBlank(content)) {
|
||||
return content;
|
||||
}
|
||||
|
||||
String processedContent = content;
|
||||
String placeholder = StringUtil.isBlank(config.getReplacement()) ?
|
||||
DEFAULT_REPLACEMENT : config.getReplacement();
|
||||
|
||||
// 1. 处理内置敏感类型
|
||||
if (!CollectionUtil.isEmpty(config.getSensitiveTypes())) {
|
||||
processedContent = processRegexPatterns(processedContent, config.getSensitiveTypes());
|
||||
}
|
||||
|
||||
// 2. 处理自定义正则
|
||||
if (!CollectionUtil.isEmpty(config.getCustomPatterns())) {
|
||||
processedContent = processCustomPatterns(processedContent,
|
||||
config.getCustomPatterns(),
|
||||
placeholder);
|
||||
}
|
||||
|
||||
// 3. 处理敏感词
|
||||
if (!CollectionUtil.isEmpty(config.getSensitiveWords())) {
|
||||
List<String> words = getSensitiveWords(config.getSensitiveWords());
|
||||
processedContent = processSensitiveWords(processedContent,
|
||||
words,
|
||||
placeholder,
|
||||
config.isProcessLineByLine());
|
||||
}
|
||||
|
||||
return processedContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理单个敏感类型
|
||||
*
|
||||
* @param content 待处理内容
|
||||
* @param type 敏感类型
|
||||
* @return 处理后的结果
|
||||
*/
|
||||
public static String process(String content, SensitiveType type) {
|
||||
if (StringUtil.isBlank(content) || type == null) {
|
||||
return content;
|
||||
}
|
||||
return processRegexPatterns(content, Collections.singleton(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理多个敏感类型
|
||||
*
|
||||
* @param content 待处理内容
|
||||
* @param types 敏感类型集合
|
||||
* @return 处理后的结果
|
||||
*/
|
||||
public static String process(String content, Set<SensitiveType> types) {
|
||||
if (StringUtil.isBlank(content) || CollectionUtil.isEmpty(types)) {
|
||||
return content;
|
||||
}
|
||||
return processRegexPatterns(content, types);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用自定义正则处理(使用默认替换符)
|
||||
*
|
||||
* @param content 待处理内容
|
||||
* @param regex 正则表达式
|
||||
* @return 处理后的结果
|
||||
*/
|
||||
public static String processWithRegex(String content, String regex) {
|
||||
return processWithRegex(content, regex, DEFAULT_REPLACEMENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用自定义正则处理(使用自定义替换符)
|
||||
*
|
||||
* @param content 待处理内容
|
||||
* @param regex 正则表达式
|
||||
* @param replacement 替换内容
|
||||
* @return 处理后的结果
|
||||
*/
|
||||
public static String processWithRegex(String content, String regex, String replacement) {
|
||||
if (StringUtil.isBlank(content) || StringUtil.isBlank(regex)) {
|
||||
return content;
|
||||
}
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
return pattern.matcher(content).replaceAll(replacement);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理敏感词(使用默认配置)
|
||||
*
|
||||
* @param content 待处理内容
|
||||
* @param words 敏感词列表
|
||||
* @return 处理后的结果
|
||||
*/
|
||||
public static String processWithWords(String content, List<String> words) {
|
||||
return processWithWords(content, words, DEFAULT_REPLACEMENT, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理敏感词(使用完整参数)
|
||||
*
|
||||
* @param content 待处理内容
|
||||
* @param words 敏感词列表
|
||||
* @param placeholder 替换符
|
||||
* @param processLineByLine 是否按行处理
|
||||
* @return 处理后的结果
|
||||
*/
|
||||
public static String processWithWords(String content,
|
||||
List<String> words,
|
||||
String placeholder,
|
||||
boolean processLineByLine) {
|
||||
if (StringUtil.isBlank(content) || CollectionUtil.isEmpty(words)) {
|
||||
return content;
|
||||
}
|
||||
return processSensitiveWords(content, words, placeholder, processLineByLine);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理正则表达式
|
||||
*/
|
||||
private static String processRegexPatterns(String content, Set<SensitiveType> types) {
|
||||
String result = content;
|
||||
for (SensitiveType type : types) {
|
||||
Pattern pattern = PATTERN_CACHE.get(type);
|
||||
result = pattern.matcher(result).replaceAll(type.getReplacement());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理自定义正则表达式
|
||||
*/
|
||||
private static String processCustomPatterns(String content,
|
||||
Map<String, Pattern> patterns,
|
||||
String placeholder) {
|
||||
String result = content;
|
||||
for (Pattern pattern : patterns.values()) {
|
||||
result = pattern.matcher(result).replaceAll(placeholder);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取敏感词列表
|
||||
*/
|
||||
private static List<String> getSensitiveWords(Set<SensitiveWord> groups) {
|
||||
List<String> words = new ArrayList<>();
|
||||
for (SensitiveWord group : groups) {
|
||||
words.addAll(group.getWords());
|
||||
}
|
||||
return words;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理敏感词
|
||||
*/
|
||||
private static String processSensitiveWords(String content,
|
||||
List<String> words,
|
||||
String placeholder,
|
||||
boolean processLineByLine) {
|
||||
return processLineByLine ?
|
||||
maskSensitiveLines(content, words, placeholder) :
|
||||
maskSensitiveContent(content, words, placeholder);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按行处理敏感词
|
||||
*/
|
||||
private static String maskSensitiveLines(String content,
|
||||
List<String> words,
|
||||
String placeholder) {
|
||||
String[] lines = content.split(LINE_SEPARATOR);
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
String line = lines[i];
|
||||
boolean containsSensitive = words.stream()
|
||||
.anyMatch(word -> line.toLowerCase().contains(word.toLowerCase()));
|
||||
|
||||
result.append(containsSensitive ? placeholder : line);
|
||||
|
||||
if (i < lines.length - 1) {
|
||||
result.append(LINE_SEPARATOR);
|
||||
}
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理整体内容中的敏感词
|
||||
*/
|
||||
private static String maskSensitiveContent(String content,
|
||||
List<String> words,
|
||||
String placeholder) {
|
||||
boolean containsSensitive = words.stream()
|
||||
.anyMatch(word -> content.toLowerCase().contains(word.toLowerCase()));
|
||||
|
||||
return containsSensitive ? placeholder : content;
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.com).
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springblade.core.tool.sensitive;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 敏感词分组枚举.
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@Getter
|
||||
public enum SensitiveWord {
|
||||
|
||||
// 安全敏感词组
|
||||
SECURE(Arrays.asList(
|
||||
// 认证信息类
|
||||
"password", "pwd", "token", "secret", "bearer", "key",
|
||||
// API相关
|
||||
"api_key", "access_token", "refresh_token", "auth_token",
|
||||
// 加密相关
|
||||
"private_key", "public_key", "salt", "hash",
|
||||
// 安全相关
|
||||
"security", "certificate", "credentials",
|
||||
// 数据库相关
|
||||
"connection_string", "jdbc", "database_url"
|
||||
)),
|
||||
|
||||
// 身份验证相关敏感词
|
||||
AUTHENTICATION(Arrays.asList(
|
||||
"otp", "verification_code", "auth_code", "mfa_token"
|
||||
));
|
||||
|
||||
private final List<String> words;
|
||||
|
||||
SensitiveWord(List<String> words) {
|
||||
this.words = Collections.unmodifiableList(words);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user