This commit is contained in:
2026-08-14 12:20:52 +08:00
parent ce0812211c
commit afd7c9d704
17 changed files with 1641 additions and 0 deletions
@@ -0,0 +1,40 @@
package com.yunhai.bschclassmanage.utils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
/**
* GZIP 压缩/解压,用于审计日志响应体(MEDIUMBLOB)存储。
*/
public class GzipUtil {
private static final int BUFFER_SIZE = 4096;
public static byte[] compress(String data) {
if (data == null) return null;
try (ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(out)) {
gzip.write(data.getBytes(StandardCharsets.UTF_8));
gzip.finish();
return out.toByteArray();
} catch (Exception e) {
throw new RuntimeException("GZIP 压缩失败", e);
}
}
public static String decompress(byte[] data) {
if (data == null || data.length == 0) return null;
try (ByteArrayInputStream in = new ByteArrayInputStream(data);
GZIPInputStream gzip = new GZIPInputStream(in);
ByteArrayOutputStream out = new ByteArrayOutputStream()) {
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = gzip.read(buf)) > 0) out.write(buf, 0, n);
return out.toString(StandardCharsets.UTF_8.name());
} catch (Exception e) {
throw new RuntimeException("GZIP 解压失败", e);
}
}
}
@@ -0,0 +1,38 @@
package com.yunhai.bschclassmanage.utils;
import com.yunhai.bschclassmanage.enums.LogLevel;
import org.apache.commons.lang3.StringUtils;
/**
* 审计日志级别/类型解析:根据 HTTP 方法 + URI + 方法名推断。
* 对齐本项目命名(save/import/upload 视为新增,delete/del/remove 视为删除)。
*/
public class OperationLogResolver {
private static final String[] DELETE_KEYWORDS = {"delete", "del", "remove"};
private static final String[] CREATE_KEYWORDS = {"add", "create", "insert", "save", "import", "upload"};
public static LogLevel resolveLevel(String httpMethod, String uri, String methodName) {
if (StringUtils.isBlank(httpMethod)) return LogLevel.SECONDARY;
String m = httpMethod.toUpperCase();
if ("GET".equals(m)) return LogLevel.GENERAL;
if ("DELETE".equals(m)) return LogLevel.IMPORTANT;
if (containsAny(uri, methodName, DELETE_KEYWORDS)) return LogLevel.IMPORTANT;
return LogLevel.SECONDARY;
}
public static String resolveOperationType(String httpMethod, String uri, String methodName) {
if (StringUtils.isBlank(httpMethod)) return "UPDATE";
String m = httpMethod.toUpperCase();
if ("GET".equals(m)) return "QUERY";
if ("DELETE".equals(m)) return "DELETE";
if (containsAny(uri, methodName, DELETE_KEYWORDS)) return "DELETE";
if (containsAny(uri, methodName, CREATE_KEYWORDS)) return "CREATE";
return "UPDATE";
}
private static boolean containsAny(String uri, String methodName, String[] keywords) {
String text = StringUtils.lowerCase(uri) + " " + StringUtils.lowerCase(methodName);
for (String kw : keywords) if (StringUtils.contains(text, kw)) return true;
return false;
}
}
@@ -0,0 +1,47 @@
package com.yunhai.bschclassmanage.utils;
import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 日志脱敏:对 request_params / response_data 中的敏感字段值掩码为 ***
* 默认敏感字段:password,pwd,secret,token,appSecret,accessKey,idCard,phone,mobile,credential
* 脱敏失败返回原文,绝不阻断主流程。
*/
public class SensitiveDataUtil {
private static volatile Set<String> SENSITIVE_KEYS = new HashSet<>(Arrays.asList(
"password", "pwd", "pass", "secret", "token", "appsecret", "accesskey",
"idcard", "phone", "mobile", "credential"
));
private static volatile Pattern FIELD_PATTERN = buildPattern();
private static Pattern buildPattern() {
return Pattern.compile(
"(\"(?i:(" + String.join("|", SENSITIVE_KEYS) + "))\"\\s*:\\s*)\"?[^,}\\s\"]+\"?",
Pattern.CASE_INSENSITIVE);
}
public static void setSensitiveKeys(Set<String> keys) {
if (keys != null && !keys.isEmpty()) {
SENSITIVE_KEYS = new HashSet<>(keys);
FIELD_PATTERN = buildPattern();
}
}
public static String mask(String json) {
if (StringUtils.isBlank(json)) return json;
try {
Matcher m = FIELD_PATTERN.matcher(json);
return m.replaceAll("$1\"***\"");
} catch (Exception e) {
return json;
}
}
}