package com.vincent.rsf.httpaudit.props; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import java.time.Duration; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * HTTP 审计配置 */ @Data @ConfigurationProperties(prefix = "http-audit") public class HttpAuditProperties { private boolean enabled = true; /** 1 数据库 2 OpenSearch 3 双写;未填或其它值同 1 */ private int logStorageMode = 1; /** 仅 2、3 使用 */ private OpenSearch openSearch = new OpenSearch(); /** 仅 1、3;无多数据源可省略 */ private String datasource = "primary"; /** 是否注册 /httpAuditRule、/httpAuditLog、/httpAuditSysConfig 等管理接口 */ private boolean adminApiEnabled = true; /** 是否提供静态查询页与 /http-audit/open/log/page(默认 true;可 simple-ui-enabled=false 关闭) */ private boolean simpleUiEnabled = true; /** 非空时要求请求头 X-Http-Audit-Ui-Token 与本值一致;留空则不校验(公网建议配置) */ private String simpleUiToken = ""; /** * true:入站/出站是否落库由 {@code sys_http_audit_rule} 匹配决定(record_all 仅影响命中条的截断;方向 IN/OUT/BOTH);false:排除路径外入站与全部出站均记录,截断用本配置默认字段 */ private boolean whitelistOnly = true; /** 规则缓存定时刷新间隔(毫秒) */ private long ruleCacheRefreshMs = 60_000L; /** 定时清理开关 */ private boolean cleanupEnabled = true; /** 保留天数 */ private int cleanupRetentionDays = 180; /** 查询类响应最多保留字符数 */ private int queryResponseMaxChars = 500; /** 非查询类响应最多入库字节(超出截断并标记) */ private int maxResponseStoreChars = 65535; /** * 规则未指定 request_max_chars 时的默认:字符数;-1 表示入库不截断请求体 */ private int defaultRequestStoreChars = 65535; /** 请求体缓存上限(字节) */ private int maxRequestCacheBytes = 2 * 1024 * 1024; /** 响应体缓存上限(字节) */ private int maxResponseCacheBytes = 2 * 1024 * 1024; /** 不落库的路径前缀 */ private List excludePathPrefixes = defaultExcludes(); /** * true:默认排除中的 /httpAuditLog、/httpAuditRule 仍生效;false:不再排除这两项(便于调试;命中规则也无法绕过 true 时的排除) */ private boolean excludeAuditSelfPaths = true; /** Filter 实际使用的前缀(受 excludeAuditSelfPaths 影响) */ public List getEffectiveExcludePrefixes() { List list = excludePathPrefixes == null ? new ArrayList<>() : new ArrayList<>(excludePathPrefixes); if (!isExcludeAuditSelfPaths()) { list.removeIf(p -> "/httpAuditLog".equals(p) || "/httpAuditRule".equals(p) || "/httpAuditSysConfig".equals(p)); } return list; } /** 视为外部调用的路径前缀(其余为内部) */ private List externalPathPrefixes = defaultExternal(); /** 路径 -> 功能描述(按最长路径前缀匹配) */ private Map pathDescriptions = new LinkedHashMap<>(); public boolean isWhitelistOnly() { return HttpAuditDbConfigHolder.getBoolean(HttpAuditDbConfigHolder.KEY_WHITELIST_ONLY, whitelistOnly); } public boolean isExcludeAuditSelfPaths() { return HttpAuditDbConfigHolder.getBoolean(HttpAuditDbConfigHolder.KEY_EXCLUDE_AUDIT_SELF_PATHS, excludeAuditSelfPaths); } public long getRuleCacheRefreshMs() { return HttpAuditDbConfigHolder.getLong(HttpAuditDbConfigHolder.KEY_RULE_CACHE_REFRESH_MS, ruleCacheRefreshMs); } public int getQueryResponseMaxChars() { return HttpAuditDbConfigHolder.getInt(HttpAuditDbConfigHolder.KEY_QUERY_RESPONSE_MAX_CHARS, queryResponseMaxChars); } public int getMaxResponseStoreChars() { return HttpAuditDbConfigHolder.getInt(HttpAuditDbConfigHolder.KEY_MAX_RESPONSE_STORE_CHARS, maxResponseStoreChars); } public int getDefaultRequestStoreChars() { return HttpAuditDbConfigHolder.getInt(HttpAuditDbConfigHolder.KEY_DEFAULT_REQUEST_STORE_CHARS, defaultRequestStoreChars); } public boolean isCleanupEnabled() { return HttpAuditDbConfigHolder.getBoolean(HttpAuditDbConfigHolder.KEY_CLEANUP_ENABLED, cleanupEnabled); } public int getCleanupRetentionDays() { return HttpAuditDbConfigHolder.getInt(HttpAuditDbConfigHolder.KEY_CLEANUP_RETENTION_DAYS, cleanupRetentionDays); } public Map getPathDescriptions() { return HttpAuditDbConfigHolder.getPathDescriptions(pathDescriptions); } public int resolveLogStorageMode() { if (logStorageMode == 2 || logStorageMode == 3) { return logStorageMode; } return 1; } public boolean usesMysqlLogStorage() { int m = resolveLogStorageMode(); return m == 1 || m == 3; } public boolean usesOpenSearchLogStorage() { int m = resolveLogStorageMode(); return m == 2 || m == 3; } @Data public static class OpenSearch { private List uris = new ArrayList<>(Collections.singletonList("localhost:9200")); private String scheme = "http"; private String username = ""; private String password = ""; private String indexName = "http_audit_log"; private Duration connectTimeout = Duration.ofSeconds(5); private Duration socketTimeout = Duration.ofSeconds(30); } private static List defaultExcludes() { List list = new ArrayList<>(); list.add("/actuator"); list.add("/swagger"); list.add("/webjars"); list.add("/v2/api-docs"); list.add("/v3/api-docs"); list.add("/doc.html"); list.add("/druid"); list.add("/error"); list.add("/favicon.ico"); list.add("/static/"); list.add("/httpAuditLog"); list.add("/httpAuditRule"); list.add("/httpAuditSysConfig"); list.add("/http-audit/"); return list; } private static List defaultExternal() { List list = new ArrayList<>(); list.add("/erp"); list.add("/cloudwms"); return list; } }